Справочник по Test API
В приведенных ниже сигнатурах типов используются следующие типы:
type Awaitable<T> = T | PromiseLike<T>;
type TestFunction = () => Awaitable<void>;
interface TestOptions {
/**
* Тест завершится с ошибкой, если время его выполнения превысит указанное значение.
*/
timeout?: number;
/**
* В случае неудачи тест будет повторен указанное количество раз.
*
* @default 0
*/
retry?: number;
/**
* Повторяет один и тот же тест несколько раз, даже если он каждый раз завершается с ошибкой.
* Если у вас есть опция "retry", и тест проваливается, каждая попытка повтора будет использована в каждом цикле.
* Полезно для отладки случайных сбоев.
*
* @default 0
*/
repeats?: number;
}Когда тестовая функция возвращает promise, исполнитель будет ожидать его разрешения для сбора асинхронных ожиданий. Если promise отклонен, тест завершится с ошибкой.
TIP
В Jest TestFunction также может иметь тип (done: DoneCallback) => void. Если используется эта форма, тест не будет завершен до тех пор, пока не будет вызван done. Вы можете добиться того же, используя async функцию, см. раздел Руководства по миграции Callback Done.
test
Тип:
(name: string | Function, fn: TestFunction, timeout?: number | TestOptions) => voidПсевдоним:
ittestопределяет набор связанных утверждений. Он принимает имя теста и функцию, содержащую утверждения для проверки.При необходимости вы можете указать тайм-аут (в миллисекундах), чтобы ограничить время ожидания завершения теста. Значение по умолчанию — 5 секунд, и его можно настроить глобально с помощью testTimeout.
tsimport { expect, test } from 'vitest'; test('должен работать как ожидается', () => { expect(Math.sqrt(4)).toBe(2); });
test.extend
Тип:
<T extends Record<string, any>>(fixtures: Fixtures<T>): TestAPI<ExtraContext & T>Псевдоним:
it.extendВерсия: Vitest 0.32.3
Используйте
test.extend, чтобы расширить контекст теста пользовательскими фикстурами. Это вернет новыйtest, который также можно расширить. Это позволяет добавлять новые фикстуры или переопределять существующие. См. Расширение контекста теста для получения дополнительной информации.tsimport { expect, test } from 'vitest'; const todos = []; const archive = []; const myTest = test.extend({ todos: async ({ task }, use) => { todos.push(1, 2, 3); await use(todos); todos.length = 0; }, archive, }); myTest('add item', ({ todos }) => { expect(todos.length).toBe(3); todos.push(4); expect(todos.length).toBe(4); });
test.skip
Тип:
(name: string | Function, fn: TestFunction, timeout?: number | TestOptions) => voidПсевдоним:
it.skipЕсли вы хотите пропустить выполнение определенных тестов, но не хотите удалять код, вы можете использовать
test.skip, чтобы исключить их из выполнения.tsimport { assert, test } from 'vitest'; test.skip('пропущенный тест', () => { // Test skipped, no error assert.equal(Math.sqrt(4), 3); });Вы также можете пропустить тест динамически, вызвав
skipв его контексте:tsimport { assert, test } from 'vitest'; test('пропущенный тест', context => { context.skip(); // Test skipped, no error assert.equal(Math.sqrt(4), 3); });
test.skipIf
Тип:
(condition: any) => TestПсевдоним:
it.skipIfВ некоторых случаях вам может потребоваться запускать тесты в разных окружениях, и некоторые тесты могут быть специфичными для определенной среды. Вместо того, чтобы оборачивать тестовый код в
if, вы можете использоватьtest.skipIf, чтобы пропустить тест, если условие истинно.tsimport { assert, test } from 'vitest'; const isDev = process.env.NODE_ENV === 'development'; test.skipIf(isDev)('тест только для prod', () => { // this test only runs in production });
WARNING
Вы не можете использовать этот синтаксис, если Vitest используется для проверки типов.
test.runIf
Тип:
(condition: any) => TestПсевдоним:
it.runIfПротивоположность test.skipIf.
tsimport { assert, test } from 'vitest'; const isDev = process.env.NODE_ENV === 'development'; test.runIf(isDev)('тест только для dev', () => { // this test only runs in development });
WARNING
Вы не можете использовать этот синтаксис, если Vitest используется для проверки типов.
test.only
Тип:
(name: string | Function, fn: TestFunction, timeout?: number) => voidПсевдоним:
it.onlyИспользуйте
test.only, чтобы запускать только определенные тесты в данном наборе. Это полезно для отладки.При необходимости вы можете указать тайм-аут (в миллисекундах), чтобы ограничить время ожидания завершения теста. Значение по умолчанию — 5 секунд, и его можно настроить глобально с помощью testTimeout.
tsimport { assert, test } from 'vitest'; test.only('test', () => { // Only this test (and others marked with only) are run assert.equal(Math.sqrt(4), 2); });Иногда бывает полезно запускать тесты
onlyв определенном файле, игнорируя все остальные тесты из всего набора, которые могут "загрязнять" вывод.Чтобы сделать это, запустите
vitestс указанием конкретного файла, содержащего интересующие тесты.# vitest interesting.test.ts
test.concurrent
Тип:
(name: string | Function, fn: TestFunction, timeout?: number) => voidПсевдоним:
it.concurrenttest.concurrentпомечает тесты для параллельного выполнения. Он принимает имя теста, асинхронную функцию, содержащую тесты, и необязательный тайм-аут (в миллисекундах).tsimport { describe, test } from 'vitest'; // The two tests marked with concurrent will be run in parallel describe('suite', () => { test('serial test', async () => { /* ... */ }); test.concurrent('concurrent test 1', async () => { /* ... */ }); test.concurrent('concurrent test 2', async () => { /* ... */ }); });test.skip,test.onlyиtest.todoработают с параллельными тестами. Допустимы следующие комбинации:tstest.concurrent(/* ... */); test.skip.concurrent(/* ... */); // или test.concurrent.skip(/* ... */) test.only.concurrent(/* ... */); // или test.concurrent.only(/* ... */) test.todo.concurrent(/* ... */); // или test.concurrent.todo(/* ... */)При выполнении параллельных тестов, для работы со снимками (Snapshots) и утверждениями (Assertions) необходимо использовать
expectиз локального Контекста теста. Это необходимо для того, чтобы убедиться, что обнаружен правильный тест.tstest.concurrent('test 1', async ({ expect }) => { expect(foo).toMatchSnapshot(); }); test.concurrent('test 2', async ({ expect }) => { expect(foo).toMatchSnapshot(); });
WARNING
Вы не можете использовать этот синтаксис, если Vitest используется для проверки типов.
test.todo
Тип:
(name: string | Function) => voidПсевдоним:
it.todoИспользуйте
test.todo, чтобы пометить тесты, которые будут реализованы позже. В отчете будет отображена запись для этих тестов, чтобы вы знали, сколько тестов вам еще предстоит реализовать.ts// An entry will be shown in the report for this test test.todo('нереализованный тест');
test.fails
Тип:
(name: string | Function, fn: TestFunction, timeout?: number) => voidПсевдоним:
it.failsИспользуйте
test.fails, чтобы указать, что тест должен завершиться с ошибкой.tsimport { expect, test } from 'vitest'; function myAsyncFunc() { return new Promise(resolve => resolve(1)); } test.fails('тест с ошибкой', async () => { await expect(myAsyncFunc()).rejects.toBe(1); });
WARNING
Вы не можете использовать этот синтаксис, если Vitest используется для проверки типов.
test.each
Тип:
(cases: ReadonlyArray<T>, ...args: any[]) => voidПсевдоним:
it.eachИспользуйте
test.each, когда вам нужно запустить один и тот же тест с разными наборами входных данных. Вы можете использовать параметры форматирования printf в имени теста, в порядке следования параметров тестовой функции.%s: string (строка)%d: number (число)%i: integer (целое число)%f: floating point value (значение с плавающей запятой)%j: json%o: object (объект)%#: index of the test case (индекс тестового случая)%%: single percent sign ('%') (одиночный знак процента ('%'))
tstest.each([ [1, 1, 2], [1, 2, 3], [2, 1, 3], ])('add(%i, %i) -> %i', (a, b, expected) => { expect(a + b).toBe(expected); }); // это вернет // ✓ add(1, 1) -> 2 // ✓ add(1, 2) -> 3 // ✓ add(2, 1) -> 3Вы также можете получить доступ к свойствам объекта с префиксом
$, если вы используете объекты в качестве аргументов:tstest.each([ { a: 1, b: 1, expected: 2 }, { a: 1, b: 2, expected: 3 }, { a: 2, b: 1, expected: 3 }, ])('add($a, $b) -> $expected', ({ a, b, expected }) => { expect(a + b).toBe(expected); }); // это вернет // ✓ add(1, 1) -> 2 // ✓ add(1, 2) -> 3 // ✓ add(2, 1) -> 3Вы также можете получить доступ к атрибутам объекта с помощью
., если вы используете объекты в качестве аргументов:tstest.each` a | b | expected ${{ val: 1 }} | ${'b'} | ${'1b'} ${{ val: 2 }} | ${'b'} | ${'2b'} ${{ val: 3 }} | ${'b'} | ${'3b'} `('add($a.val, $b) -> $expected', ({ a, b, expected }) => { expect(a.val + b).toBe(expected); }); // это вернет // ✓ add(1, b) -> 1b // ✓ add(2, b) -> 2b // ✓ add(3, b) -> 3bНачиная с Vitest 0.25.3, вы также можете использовать табличный шаблон строки.
- Первая строка должна содержать имена столбцов, разделенные
|; - Одна или несколько последующих строк данных, предоставленных в виде выражений шаблонных литералов с использованием синтаксиса
${value}.
tstest.each` a | b | expected ${1} | ${1} | ${2} ${'a'} | ${'b'} | ${'ab'} ${[]} | ${'b'} | ${'b'} ${{}} | ${'b'} | ${'[object Object]b'} ${{ asd: 1 }} | ${'b'} | ${'[object Object]b'} `('returns $expected when $a is added $b', ({ a, b, expected }) => { expect(a + b).toBe(expected); });Если вам нужен доступ к
TestContext, используйтеdescribe.eachс одним тестом.
TIP
Vitest обрабатывает $values с помощью метода format chai. Если значение усекается, вы можете увеличить chaiConfig.truncateThreshold в файле конфигурации.
WARNING
Вы не можете использовать этот синтаксис, если Vitest используется для проверки типов.
bench
- Тип:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
bench определяет бенчмарк (тест производительности). В Vitest бенчмарк — это функция, определяющая последовательность операций. Vitest запускает эту функцию несколько раз для получения различных показателей производительности.
Vitest использует библиотеку tinybench под капотом, наследуя все ее параметры, которые можно использовать в качестве третьего аргумента.
import { bench } from 'vitest';
bench(
'обычная сортировка',
() => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
},
{ time: 1000 }
);export interface Options {
/**
* Время, необходимое для выполнения задачи бенчмарка (в миллисекундах).
* @default 500
*/
time?: number;
/**
* Количество раз, которое задача должна выполняться, даже если опция времени завершена.
* @default 10
*/
iterations?: number;
/**
* Функция для получения текущей временной метки в миллисекундах.
*/
now?: () => number;
/**
* AbortSignal для прерывания бенчмарка.
*/
signal?: AbortSignal;
/**
* Время на разогрев (в миллисекундах).
* @default 100ms
*/
warmupTime?: number;
/**
* Итерации прогрева.
* @default 5
*/
warmupIterations?: number;
/**
* Функция настройки для запуска перед каждой задачей бенчмарка (циклом).
*/
setup?: Hook;
/**
* Функция завершения для запуска после каждой задачи бенчмарка (цикла).
*/
teardown?: Hook;
}bench.skip
- Тип:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
Вы можете использовать синтаксис bench.skip, чтобы пропустить выполнение определенных бенчмарков.
import { bench } from 'vitest';
bench.skip('обычная сортировка', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});bench.only
- Тип:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
Используйте bench.only, чтобы запускать только определенные бенчмарки в данном наборе. Это полезно для отладки.
import { bench } from 'vitest';
bench.only('обычная сортировка', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});bench.todo
- Тип:
(name: string | Function) => void
Используйте bench.todo, чтобы пометить бенчмарки, которые будут реализованы позже.
import { bench } from 'vitest';
bench.todo('нереализованный тест');describe
Когда вы используете test или bench на верхнем уровне файла, они автоматически объединяются в неявный набор тестов (suite). Используя describe, вы можете определить новый набор в текущем контексте, представляющий собой группу связанных тестов, бенчмарков или других вложенных наборов. Набор позволяет организовать тесты и бенчмарки, делая отчеты более наглядными.
// basic.spec.ts
// organizing tests
import { describe, expect, test } from 'vitest';
const person = {
isActive: true,
age: 32,
};
describe('person', () => {
test('person is defined', () => {
expect(person).toBeDefined();
});
test('is active', () => {
expect(person.isActive).toBeTruthy();
});
test('age limit', () => {
expect(person.age).toBeLessThanOrEqual(32);
});
});// basic.bench.ts
// organizing benchmarks
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;
});
});
});Вы также можете вкладывать блоки describe, если у вас есть иерархическая структура тестов или бенчмарков:
import { describe, expect, test } from 'vitest';
function numberToCurrency(value) {
if (typeof value !== 'number') throw new Error('Value must be a number');
return value
.toFixed(2)
.toString()
.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
describe('numberToCurrency', () => {
describe('given an invalid number', () => {
test('composed of non-numbers to throw error', () => {
expect(() => numberToCurrency('abc')).toThrowError();
});
});
describe('given a valid number', () => {
test('returns the correct currency format', () => {
expect(numberToCurrency(10000)).toBe('10,000.00');
});
});
});describe.skip
Тип:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => voidИспользуйте
describe.skipв тест-сьюте, чтобы пропустить выполнение определенного блокаdescribe.tsimport { assert, describe, test } from 'vitest'; describe.skip('skipped suite', () => { test('sqrt', () => { // Suite skipped, no error assert.equal(Math.sqrt(4), 3); }); });
describe.skipIf
Тип:
(condition: any) => voidВ некоторых случаях вам может потребоваться запускать тест-сьюты несколько раз в разных окружениях, и некоторые из них могут быть специфичными для определенного окружения. Вместо того чтобы оборачивать тест-сьют в
if, вы можете использоватьdescribe.skipIf, чтобы пропустить набор, если условие истинно.tsimport { describe, test } from 'vitest'; const isDev = process.env.NODE_ENV === 'development'; describe.skipIf(isDev)('prod only test', () => { // this test only runs in production });
WARNING
Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.
describe.only
Тип:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => voidИспользуйте
describe.only, чтобы запускать только определенные тест-сьюты.ts// Only this suite (and others marked with only) are run describe.only('suite', () => { test('sqrt', () => { assert.equal(Math.sqrt(4), 3); }); }); describe('other suite', () => { // ... will be skipped });Иногда полезно запускать тесты
onlyв конкретном файле, игнорируя все остальные тесты из всего набора, которые загромождают вывод.Чтобы сделать это, запустите
vitestс указанием конкретного файла, содержащего интересующие тесты.# vitest interesting.test.ts
describe.concurrent
Тип:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => voiddescribe.concurrentв тест-сьюте помечает все тесты внутри него как параллельные.ts// All tests within this suite will be run in parallel describe.concurrent('suite', () => { test('concurrent test 1', async () => { /* ... */ }); test('concurrent test 2', async () => { /* ... */ }); test.concurrent('concurrent test 3', async () => { /* ... */ }); });.skip,.onlyи.todoработают с параллельными тест-сьютами. Все следующие комбинации являются допустимыми:tsdescribe.concurrent(/* ... */); describe.skip.concurrent(/* ... */); // or describe.concurrent.skip(/* ... */) describe.only.concurrent(/* ... */); // or describe.concurrent.only(/* ... */) describe.todo.concurrent(/* ... */); // or describe.concurrent.todo(/* ... */)
При запуске параллельных тестов, Снимки (Snapshots) и Утверждения (Assertions) должны использовать expect из локального Контекста Теста, чтобы убедиться, что обнаружен правильный тест.
describe.concurrent('suite', () => {
test('concurrent test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test('concurrent test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
});WARNING
Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.
describe.sequential
Тип:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => voiddescribe.sequentialв тест-сьюте помечает каждый тест как последовательный. Это полезно, если требуется запускать тесты последовательно внутриdescribe.concurrentили при использовании опции командной строки--sequence.concurrent.tsdescribe.concurrent('suite', () => { test('concurrent test 1', async () => { /* ... */ }); test('concurrent test 2', async () => { /* ... */ }); describe.sequential('', () => { test('sequential test 1', async () => { /* ... */ }); test('sequential test 2', async () => { /* ... */ }); }); });
describe.shuffle
Тип:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => voidVitest предоставляет способ запускать все тесты в случайном порядке с помощью флага CLI
--sequence.shuffleили опции конфигурацииsequence.shuffle, но если вы хотите, чтобы только часть тестов в вашем наборе запускалась в случайном порядке, вы можете отметить этот набор с помощью этого флага.tsdescribe.shuffle('suite', () => { test('random test 1', async () => { /* ... */ }); test('random test 2', async () => { /* ... */ }); test('random test 3', async () => { /* ... */ }); }); // order depends on sequence.seed option in config (Date.now() by default)
.skip, .only и .todo работают со случайными тест-сьютами.
WARNING
Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.
describe.todo
Тип:
(name: string | Function) => voidИспользуйте
describe.todo, чтобы создать заготовки для тест-сьютов, которые будут реализованы позже. В отчете будет отображаться запись для этих тестов, чтобы вы знали, сколько тестов вам еще нужно реализовать.ts// An entry will be shown in the report for this suite describe.todo('unimplemented suite');
describe.each
Тип:
(cases: ReadonlyArray<T>, ...args: any[]): (name: string | Function, fn: (...args: T[]) => void, options?: number | TestOptions) => voidИспользуйте
describe.each, если у вас есть несколько тестов, которые зависят от одних и тех же данных.tsdescribe.each([ { a: 1, b: 1, expected: 2 }, { a: 1, b: 2, expected: 3 }, { a: 2, b: 1, expected: 3 }, ])('describe object add($a, $b)', ({ a, b, expected }) => { test(`returns ${expected}`, () => { expect(a + b).toBe(expected); }); test(`returned value not be greater than ${expected}`, () => { expect(a + b).not.toBeGreaterThan(expected); }); test(`returned value not be less than ${expected}`, () => { expect(a + b).not.toBeLessThan(expected); }); });Начиная с Vitest 0.25.3, вы также можете использовать шаблонные строки в виде таблицы.
- Первая строка должна содержать имена столбцов, разделенные символом
|; - Одна или несколько последующих строк данных, предоставленных в виде выражений строковых литералов с использованием синтаксиса
${value}.
tsdescribe.each` a | b | expected ${1} | ${1} | ${2} ${'a'} | ${'b'} | ${'ab'} ${[]} | ${'b'} | ${'b'} ${{}} | ${'b'} | ${'[object Object]b'} ${{ asd: 1 }} | ${'b'} | ${'[object Object]b'} `('describe template string add($a, $b)', ({ a, b, expected }) => { test(`returns ${expected}`, () => { expect(a + b).toBe(expected); }); });- Первая строка должна содержать имена столбцов, разделенные символом
WARNING
Вы не можете использовать этот синтаксис при использовании Vitest в качестве проверки типов.
Setup and Teardown
Эти функции позволяют взаимодействовать с жизненным циклом тестов, чтобы избежать повторения кода инициализации и завершения. Они применяются к текущему контексту: к файлу, если они используются на верхнем уровне файла, или к текущему тест-сьюту, если они находятся внутри блока describe. Эти хуки не вызываются, когда вы запускаете Vitest в качестве проверки типов.
beforeEach
Тип:
beforeEach(fn: () => Awaitable<void>, timeout?: number)Регистрирует функцию обратного вызова (callback), которая будет вызвана перед каждым тестом в текущем контексте. Если функция возвращает промис, Vitest ждет, пока промис не будет разрешен, прежде чем запускать тест.
При необходимости вы можете передать тайм-аут (в миллисекундах), определяющий, как долго ждать перед завершением. Значение по умолчанию - 5 секунд.
tsimport { beforeEach } from 'vitest'; beforeEach(async () => { // Clear mocks and add some testing data after before each test run await stopMocking(); await addUser({ name: 'John' }); });Здесь
beforeEachгарантирует, что пользователь будет добавлен перед каждым тестом.Начиная с Vitest v0.10.0,
beforeEachтакже принимает необязательную функцию очистки (cleanup function) (эквивалентнуюafterEach).tsimport { beforeEach } from 'vitest'; beforeEach(async () => { // called once before each test run await prepareSomething(); // clean up function, called once after each test run return async () => { await resetSomething(); }; });
afterEach
Тип:
afterEach(fn: () => Awaitable<void>, timeout?: number)Регистрирует обратный вызов, который будет вызван после завершения каждого теста в текущем контексте. Если функция возвращает промис, Vitest ждет, пока промис не будет разрешен, прежде чем продолжить.
При необходимости вы можете указать тайм-аут (в миллисекундах) для указания, как долго ждать перед завершением. Значение по умолчанию - 5 секунд.
tsimport { afterEach } from 'vitest'; afterEach(async () => { await clearTestingData(); // clear testing data after each test run });Здесь
afterEachгарантирует, что тестовые данные будут очищены после каждого запуска теста.
beforeAll
Тип:
beforeAll(fn: () => Awaitable<void>, timeout?: number)Регистрирует обратный вызов, который будет вызван один раз перед началом запуска всех тестов в текущем контексте. Если функция возвращает промис, Vitest ждет, пока промис не будет разрешен, прежде чем запускать тесты.
При необходимости вы можете указать тайм-аут (в миллисекундах) для указания, как долго ждать перед завершением. Значение по умолчанию - 5 секунд.
tsimport { beforeAll } from 'vitest'; beforeAll(async () => { await startMocking(); // called once before all tests run });Здесь
beforeAllгарантирует, что mock-данные будут настроены перед запуском тестов.Начиная с Vitest v0.10.0,
beforeAllтакже принимает необязательную функцию очистки (cleanup function) (эквивалентнуюafterAll).tsimport { beforeAll } from 'vitest'; beforeAll(async () => { // called once before all tests run await startMocking(); // clean up function, called once after all tests run return async () => { await stopMocking(); }; });
afterAll
Тип:
afterAll(fn: () => Awaitable<void>, timeout?: number)Регистрирует обратный вызов, который будет вызван один раз после того, как все тесты будут запущены в текущем контексте. Если функция возвращает промис, Vitest ждет, пока промис не будет разрешен, прежде чем продолжить.
При необходимости вы можете указать тайм-аут (в миллисекундах) для указания, как долго ждать перед завершением. Значение по умолчанию - 5 секунд.
tsimport { afterAll } from 'vitest'; afterAll(async () => { await stopMocking(); // this method is called after all tests run });Здесь
afterAllгарантирует, что методstopMockingбудет вызван после запуска всех тестов.