Vitest тесно интегрирован с Vite и использует его конфигурацию как основу для запуска тестов. Благодаря этому тестовая среда автоматически наследует:
Основная идея заключается в том, что тесты выполняются в том же окружении, что и приложение. Это избавляет от дублирования конфигурации и делает поведение тестов максимально приближенным к реальной сборке.
Vitest может настраиваться прямо внутри vite.config.js,
vite.config.ts или отдельного файла
vitest.config.ts.
Простейшая конфигурация внутри vite.config.ts:
import { defineConfig } from 'vite'
export default defineConfig({
test: {
globals: true
}
})
Для TypeScript чаще используется импорт из
vitest/config:
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true
}
})
Причина использования vitest/config связана с
типизацией. Этот вариант позволяет IDE корректно понимать секцию
test.
После установки:
npm install -D vitest
в package.json обычно добавляется:
{
"scripts": {
"test": "vitest"
}
}
Запуск:
npm run test
Режим наблюдения:
npm run test -- --watch
Однократный запуск:
npm run test -- --run
testВсе параметры Vitest располагаются внутри свойства
test.
Пример расширенной конфигурации:
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
environment: 'jsdom',
watch: false,
include: ['src/**/*.test.ts'],
exclude: ['node_modules', 'dist']
}
})
globalsПо умолчанию Vitest требует явного импорта тестовых функций:
import { describe, it, expect } from 'vitest'
При включении:
test: {
globals: true
}
глобально становятся доступны:
describeittestexpectbeforeEachafterEachviТогда тест можно писать так:
describe('sum', () => {
it('adds numbers', () => {
expect(1 + 1).toBe(2)
})
})
globalsВ крупных проектах часто предпочитают явные импорты.
environmentОпределяет среду выполнения тестов.
nodeИспользуется по умолчанию.
test: {
environment: 'node'
}
Подходит для:
jsdomЭмулирует браузер.
test: {
environment: 'jsdom'
}
Необходим для:
Пример:
document.body.innerHTML = `
<button id="btn">Click</button>
`
const button = document.querySelector('#btn')
expect(button?.textContent).toBe('Click')
Без jsdom объект document отсутствует.
happy-domАльтернативная браузерная среда.
test: {
environment: 'happy-dom'
}
Особенности:
jsdom;Часто используется для ускорения CI.
includeОпределяет список тестовых файлов.
test: {
include: ['src/**/*.test.ts']
}
Поддерживаются:
Пример:
include: [
'src/**/*.test.ts',
'src/**/*.spec.ts'
]
excludeИсключает файлы из тестирования.
test: {
exclude: [
'node_modules',
'dist',
'.idea'
]
}
Часто сюда добавляют:
exclude: [
'**/e2e/**',
'**/coverage/**'
]
watchУправляет режимом наблюдения.
test: {
watch: false
}
Если true, Vitest автоматически перезапускает тесты при
изменениях файлов.
setupFilesПозволяет запускать код перед стартом тестов.
test: {
setupFiles: ['./tests/setup.ts']
}
import '@testing-library/jest-dom'
Или:
beforeEach(() => {
localStorage.clear()
})
cssУправляет обработкой CSS.
test: {
css: true
}
Особенно полезно при тестировании:
mockResetАвтоматически сбрасывает mock-функции.
test: {
mockReset: true
}
Эквивалентно:
beforeEach(() => {
vi.resetAllMocks()
})
clearMocksОчищает историю вызовов.
test: {
clearMocks: true
}
Разница:
clearMocks — очищает вызовы;mockReset — очищает реализацию и вызовы;restoreMocks — восстанавливает оригинальные
методы.restoreMockstest: {
restoreMocks: true
}
Полезно при использовании:
vi.spyOn()
coverageНастройка покрытия кода.
Пример:
test: {
coverage: {
provider: 'v8',
reporter: ['text', 'html']
}
}
v8provider: 'v8'
Преимущества:
istanbulprovider: 'istanbul'
Особенности:
v8.reporter: ['text', 'json', 'html']
Популярные варианты:
textjsonhtmllcovvitest run --coverage
aliasVitest использует алиасы Vite.
import path from 'node:path'
import { defineConfig } from 'vitest/config'
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
}
})
Тогда:
import Button from '@/components/Button'
работает одинаково:
Vitest автоматически применяет Vite-плагины.
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vitest/config'
export default defineConfig({
plugins: [react()]
})
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()]
})
import { svelte } from '@sveltejs/vite-plugin-svelte'
export default defineConfig({
plugins: [svelte()]
})
Vitest автоматически использует tsconfig.json.
Пример:
{
"compilerOptions": {
"types": ["vitest/globals"]
}
}
Это необходимо при использовании:
globals: true
Иногда Vite и Vitest конфигурируются отдельно.
vitest.config.tsimport { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true
}
})
import { mergeConfig } from 'vite'
import viteConfig from './vite.config'
import { defineConfig } from 'vitest/config'
export default mergeConfig(
viteConfig,
defineConfig({
test: {
globals: true
}
})
)
Это позволяет:
testTimeoutУстанавливает таймаут тестов.
test: {
testTimeout: 5000
}
Пример:
it('fetches data', async () => {
await fetchData()
}, 5000)
hookTimeoutТаймаут lifecycle-хуков:
test: {
hookTimeout: 10000
}
Относится к:
beforeAllbeforeEachafterEachafterAllretryПовтор тестов при ошибке.
test: {
retry: 2
}
Полезно для:
threadsVitest поддерживает многопоточность.
test: {
threads: true
}
Отключение:
threads: false
Иногда требуется при:
reportersОпределяет формат вывода результатов.
test: {
reporters: ['default']
}
Другие варианты:
reporters: [
'verbose',
'json',
'junit'
]
outputFileИспользуется вместе с json или junit.
test: {
reporters: ['json'],
outputFile: './reports/tests.json'
}
Vitest поддерживает запуск тестов в браузере.
Пример:
test: {
browser: {
enabled: true,
name: 'chrome'
}
}
Поддерживаются:
defineConfigРекомендуемый вариант:
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true
}
})
Преимущества:
import path from 'node:path'
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vitest/config'
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
},
test: {
globals: true,
environment: 'jsdom',
include: [
'src/**/*.test.ts',
'src/**/*.spec.tsx'
],
exclude: [
'node_modules',
'dist',
'e2e'
],
setupFiles: ['./tests/setup.ts'],
css: true,
clearMocks: true,
restoreMocks: true,
testTimeout: 5000,
coverage: {
provider: 'v8',
reporter: ['text', 'html']
}
}
})
project/
├── src/
├── tests/
│ ├── setup.ts
│ └── unit/
├── vite.config.ts
├── vitest.config.ts
├── tsconfig.json
└── package.json
document is not definedПричина:
environment: 'node'
Решение:
environment: 'jsdom'
Причина:
resolve.alias;vitest.config.ts без merge.Решение:
{
"compilerOptions": {
"types": ["vitest/globals"]
}
}
Причины:
defineConfig;| Возможность | Vitest | Jest |
|---|---|---|
| Использует Vite | Да | Нет |
| ESM | Нативно | Ограниченно |
| Скорость HMR | Очень высокая | Ниже |
| Конфигурация | Через Vite | Отдельная |
| Трансформация TS | esbuild | babel/ts-jest |
| Browser Mode | Есть | Ограниченно |
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vitest/config'
export default defineConfig({
plugins: [react()],
test: {
environment: 'jsdom',
globals: true,
setupFiles: ['./src/tests/setup.ts']
}
})
setup.ts:
import '@testing-library/jest-dom'
import vue from '@vitejs/plugin-vue'
import { defineConfig } from 'vitest/config'
export default defineConfig({
plugins: [vue()],
test: {
environment: 'jsdom',
globals: true
}
})
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
environment: 'node',
globals: false,
threads: true
}
})
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
projects: [
'./packages/frontend',
'./packages/backend'
]
}
})
Такой подход позволяет: