Возможности
- Конфигурация, трансформаторы, резолверы и плагины Vite
- Использование той же конфигурации, что и в вашем приложении, для запуска тестов.
- Интеллектуальный и мгновенный режим отслеживания изменений, аналогичный HMR для тестов!
- Тестирование компонентов для Vue, React, Svelte, Lit, Marko и других фреймворков.
- Поддержка TypeScript и JSX "из коробки".
- Приоритет ESM, поддержка
top-level await
. - Многопоточность воркеров через Tinypool.
- Поддержка бенчмаркинга с Tinybench.
- Фильтрация, таймауты и параллельное выполнение для наборов и отдельных тестов.
- Поддержка проектов.
- Jest-совместимые снимки.
- Встроенный Chai для утверждений и совместимые API с Jest expect.
- Встроенный Tinyspy для создания моков.
- happy-dom или jsdom для мокирования DOM.
- Режим браузера для запуска тестов компонентов в браузере.
- Покрытие кода с помощью v8 или istanbul.
- Встроенное тестирование в стиле Rust.
- Тестирование типов через expect-type.
- Поддержка шардинга.
- Отчеты о необработанных ошибках.
Общая конфигурация между тестом, разработкой и сборкой
Vitest использует конфигурацию, трансформаторы, резолверы и плагины Vite. Это позволяет использовать ту же конфигурацию, что и в вашем приложении, для запуска тестов.
Подробнее см. в разделе Настройка Vitest.
Режим отслеживания изменений
$ vitest
При изменении исходного кода или тестовых файлов Vitest интеллектуально анализирует граф модулей и перезапускает только связанные тесты, точно так же, как работает HMR в Vite!
vitest
по умолчанию использует watch mode
в среде разработки и run mode
в среде CI (когда присутствует process.env.CI
). Вы можете явно указать желаемый режим, используя vitest watch
или vitest run
.
Запустите Vitest с флагом --standalone
, чтобы он продолжал работать в фоновом режиме. В этом режиме тесты не будут запускаться до тех пор, пока не произойдут изменения. Vitest не будет запускать тесты при изменении исходного кода, пока не будет выполнен тест, который его импортирует.
Общие веб-идиомы "из коробки"
Поддержка ES Module / TypeScript / JSX / PostCSS доступна "из коробки".
Потоки
По умолчанию Vitest запускает тестовые файлы в нескольких процессах с использованием node:child_process
через Tinypool (легковесный форк Piscina), обеспечивая одновременное выполнение тестов. Если вы хотите еще больше ускорить свой тестовый набор, рассмотрите возможность включения --pool=threads
для запуска тестов с использованием node:worker_threads
(учтите, что некоторые пакеты могут быть несовместимы с этим режимом).
Чтобы запустить тесты в одном потоке или процессе, см. poolOptions
.
Vitest также изолирует среду каждого файла, чтобы изменения окружения в одном файле не влияли на другие. Изоляцию можно отключить, передав --no-isolate
в CLI (это повысит производительность за счет потенциального снижения корректности).
Фильтрация тестов
Vitest предоставляет множество способов ограничить набор запускаемых тестов, чтобы ускорить тестирование и позволить вам сосредоточиться на разработке.
Подробнее о фильтрации тестов.
Параллельный запуск тестов
Используйте .concurrent
для параллельного запуска отдельных тестов.
import { describe, it } from 'vitest';
// Два теста, помеченные как concurrent, будут запущены параллельно
describe('suite', () => {
it('serial test', async () => {
/* ... */
});
it.concurrent('concurrent test 1', async ({ expect }) => {
/* ... */
});
it.concurrent('concurrent test 2', async ({ expect }) => {
/* ... */
});
});
Если вы используете .concurrent
для тестового набора, каждый тест в нем будет запущен параллельно.
import { describe, it } from 'vitest';
// Все тесты в этом наборе будут запущены параллельно
describe.concurrent('suite', () => {
it('concurrent test 1', async ({ expect }) => {
/* ... */
});
it('concurrent test 2', async ({ expect }) => {
/* ... */
});
it.concurrent('concurrent test 3', async ({ expect }) => {
/* ... */
});
});
Вы также можете использовать .skip
, .only
и .todo
с параллельными наборами и тестами. Подробнее см. в справочнике API.
WARNING
При запуске параллельных тестов снимки и утверждения должны использовать expect
из локального контекста теста, чтобы гарантировать корректное определение теста.
Снимки
Поддержка снимков, совместимых с Jest.
import { expect, it } from 'vitest';
it('renders correctly', () => {
const result = render();
expect(result).toMatchSnapshot();
});
Подробнее см. Снимки.
Совместимость Chai и Jest expect
Chai встроен для использования в утверждениях с Jest expect
-совместимыми API.
Обратите внимание, что если вы используете сторонние библиотеки, добавляющие матчеры, установка test.globals
в true
улучшит совместимость.
Мокирование
Tinyspy встроен для мокирования с jest
-совместимыми API, доступными через объект vi
.
import { expect, vi } from 'vitest';
const fn = vi.fn();
fn('hello', 1);
expect(vi.isMockFunction(fn)).toBe(true);
expect(fn.mock.calls[0]).toEqual(['hello', 1]);
fn.mockImplementation((arg: string) => arg);
fn('world', 2);
expect(fn.mock.results[1].value).toBe('world');
Vitest поддерживает как happy-dom, так и jsdom для создания моков DOM и API браузера. Они не входят в комплект Vitest, вам потребуется установить их отдельно:
$ npm i -D happy-dom
$ npm i -D jsdom
После этого измените опцию environment
в вашем файле конфигурации:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'happy-dom', // или 'jsdom', 'node'
},
});
Подробнее см. в разделе Мокирование.
Покрытие
Vitest поддерживает нативное покрытие кода через v8
и инструментальное покрытие кода через istanbul
.
{
"scripts": {
"test": "vitest",
"coverage": "vitest run --coverage"
}
}
Подробнее см. Покрытие.
Встроенное тестирование
Vitest также предоставляет способ запуска тестов непосредственно в исходном коде вместе с реализацией, аналогично модульным тестам Rust.
Это позволяет тестам использовать то же замыкание, что и реализации, а также тестировать приватные состояния без необходимости их экспорта. При этом это также сокращает цикл обратной связи в процессе разработки.
// реализация
export function add(...args: number[]): number {
return args.reduce((a, b) => a + b, 0);
}
// встроенные тестовые наборы
if (import.meta.vitest) {
const { it, expect } = import.meta.vitest;
it('add', () => {
expect(add()).toBe(0);
expect(add(1)).toBe(1);
expect(add(1, 2, 3)).toBe(6);
});
}
Подробнее см. Встроенное тестирование.
Бенчмаркинг Экспериментально
Вы можете запускать бенчмарк-тесты с помощью функции bench
через Tinybench для сравнения результатов производительности.
import { bench, describe } from 'vitest';
describe('sort', () => {
bench('normal', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});
bench('reverse', () => {
const x = [1, 5, 4, 2, 3];
x.reverse().sort((a, b) => {
return a - b;
});
});
});
Тестирование типов Экспериментально
Вы можете писать тесты для выявления регрессий типов. Vitest включает пакет expect-type
, который предоставляет аналогичный и простой для понимания API.
import { assertType, expectTypeOf, test } from 'vitest';
import { mount } from './mount.js';
test('my types work properly', () => {
expectTypeOf(mount).toBeFunction();
expectTypeOf(mount).parameter(0).toMatchTypeOf<{ name: string }>();
// @ts-expect-error name is a string
assertType(mount({ name: 42 }));
});
Шардинг
Запускайте тесты на разных машинах с помощью флагов --shard
и --reporter=blob
. Все результаты тестов и покрытия могут быть объединены по завершении вашего CI-пайплайна с помощью команды --merge-reports
:
vitest --shard=1/2 --reporter=blob --coverage
vitest --shard=2/2 --reporter=blob --coverage
vitest --merge-reports --reporter=junit --coverage
Дополнительную информацию см. в Улучшение производительности | Шардинг
.
Переменные окружения
Vitest автоматически загружает только переменные окружения, начинающиеся с VITE_
, из файлов .env
, чтобы обеспечить совместимость с фронтенд-тестами, следуя установленной конвенции Vite. Чтобы загрузить все переменные окружения из файлов .env
, вы можете использовать метод loadEnv
, импортированный из vite
:
import { loadEnv } from 'vite';
import { defineConfig } from 'vitest/config';
export default defineConfig(({ mode }) => ({
test: {
// mode определяет, какой файл ".env.{mode}" выбрать, если он существует
env: loadEnv(mode, process.cwd(), ''),
},
}));
Необработанные ошибки
По умолчанию Vitest перехватывает и сообщает обо всех необработанных отклонениях промисов, необработанных исключениях (в Node.js) и ошибках (в браузере).
Вы можете отключить это поведение, обрабатывая их вручную. Vitest предполагает, что вы обрабатываете обратный вызов, и не будет сообщать об ошибке.
// в Node.js
process.on('unhandledRejection', () => {
// ваш собственный обработчик
});
process.on('uncaughtException', () => {
// ваш собственный обработчик
});
// в браузере
window.addEventListener('error', () => {
// ваш собственный обработчик
});
window.addEventListener('unhandledrejection', () => {
// ваш собственный обработчик
});
В качестве альтернативы вы также можете игнорировать ошибки, о которых сообщает Vitest, используя опцию dangerouslyIgnoreUnhandledErrors
. Vitest все равно будет сообщать о них, но это не повлияет на результат теста (код выхода останется прежним).
Если вам нужно проверить, что ошибка не была обработана, вы можете создать тест, который выглядит следующим образом:
test('my function throws uncaught error', async ({ onTestFinished }) => {
onTestFinished(() => {
// если событие не было вызвано во время теста,
// убедитесь, что оно удалено до начала следующего теста
process.removeAllListeners('unhandledrejection');
});
return new Promise((resolve, reject) => {
process.once('unhandledrejection', error => {
try {
expect(error.message).toBe('my error');
resolve();
} catch (error) {
reject(error);
}
});
callMyFunctionThatRejectsError();
});
});