13. Тестирование с Vitest
Vitest — это современный тест-раннер, созданный специально для Vite-проектов. Он использует ту же конфигурацию vite.config.ts, поддерживает ESM из коробки и работает значительно быстрее Jest благодаря нативной интеграции с Vite.
Установка и настройка
Заголовок раздела «Установка и настройка»npm i -D vitest# или с jsdom для тестирования DOMnpm i -D vitest jsdom @testing-library/react @testing-library/jest-domКонфигурация в vite.config.ts
Заголовок раздела «Конфигурация в vite.config.ts»import { defineConfig } from 'vite'import react from '@vitejs/plugin-react'
export default defineConfig({ plugins: [react()], test: { // Среда выполнения тестов environment: 'jsdom', // 'node' | 'jsdom' | 'happy-dom'
// Глобальные функции (describe, it, expect без импорта) globals: true,
// Setup файл (импорт jest-dom матчеров) setupFiles: ['./src/setupTests.ts'],
// Coverage coverage: { provider: 'v8', // 'v8' | 'istanbul' reporter: ['text', 'html', 'lcov'], include: ['src/**'], exclude: ['src/**/*.stories.tsx'], thresholds: { lines: 80, functions: 80, branches: 70, }, },
// Параллельное выполнение pool: 'threads', // 'threads' | 'forks' | 'vmThreads' poolOptions: { threads: { singleThread: false, }, }, },})Написание тестов
Заголовок раздела «Написание тестов»import { describe, it, expect } from 'vitest'import { add, multiply, factorial } from './math'
describe('math utils', () => { describe('add()', () => { it('складывает два числа', () => { expect(add(2, 3)).toBe(5) })
it('работает с отрицательными числами', () => { expect(add(-1, 1)).toBe(0) }) })
it('factorial(5) === 120', () => { expect(factorial(5)).toBe(120) })})Тестирование React компонентов
Заголовок раздела «Тестирование React компонентов»import { render, screen, fireEvent } from '@testing-library/react'import { describe, it, expect, vi } from 'vitest'import { Button } from './Button'
describe('Button', () => { it('отображает текст', () => { render(<Button>Click me</Button>) expect(screen.getByText('Click me')).toBeInTheDocument() })
it('вызывает onClick при клике', () => { const handleClick = vi.fn() render(<Button onClick={handleClick}>Click me</Button>) fireEvent.click(screen.getByText('Click me')) expect(handleClick).toHaveBeenCalledOnce() })
it('disabled кнопка не реагирует на клики', () => { const handleClick = vi.fn() render(<Button disabled onClick={handleClick}>Disabled</Button>) fireEvent.click(screen.getByText('Disabled')) expect(handleClick).not.toHaveBeenCalled() })})Vitest специфичные возможности
Заголовок раздела «Vitest специфичные возможности»// Mock функцииimport { vi } from 'vitest'
// Мок модуляvi.mock('./api', () => ({ fetchUser: vi.fn().mockResolvedValue({ id: 1, name: 'Alice' }),}))
// Шпионconst spy = vi.spyOn(console, 'error')expect(spy).toHaveBeenCalledWith('Expected error')
// Таймерыvi.useFakeTimers()vi.advanceTimersByTime(1000)vi.useRealTimers()
// Инлайн снапшотыexpect(result).toMatchInlineSnapshot(\` { "name": "Alice", "age": 30, }\`)CLI команды
Заголовок раздела «CLI команды»# Запуск всех тестовnpx vitest
# Watch mode (для разработки)npx vitest --watch
# UI mode — красивый веб-интерфейсnpx vitest --ui
# Coveragenpx vitest run --coverage
# Конкретный файлnpx vitest Button.test.tsx
# Bench (бенчмарки производительности)npx vitest benchVitest UI
Заголовок раздела «Vitest UI»npm i -D @vitest/uinpx vitest --uiНиже — симулятор тест-раннера: запускай тесты и смотри результаты: