Справочник по 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.
Большинство опций поддерживают как точечный синтаксис, так и объектный синтаксис, позволяя вам использовать любой стиль, который вы предпочитаете.
import { test } from 'vitest';
test.skip('skipped test', () => {
// some logic that fails right now
});import { test } from 'vitest';
test('skipped test', { skip: true }, () => {
// some logic that fails right now
});test
- Псевдоним:
it
test определяет набор связанных утверждений. Он принимает имя теста и функцию, содержащую утверждения для проверки.
При необходимости вы можете указать тайм-аут (в миллисекундах), чтобы ограничить время ожидания завершения теста. Значение по умолчанию — 5 секунд, и его можно настроить глобально с помощью testTimeout.
import { expect, test } from 'vitest';
test('должен работать как ожидается', () => {
expect(Math.sqrt(4)).toBe(2);
});test.extend
- Псевдоним:
it.extend
Используйте test.extend, чтобы расширить контекст теста пользовательскими фикстурами. Это вернет новый test, который также можно расширить. Это позволяет добавлять новые фикстуры или переопределять существующие. См. Расширение контекста теста для получения дополнительной информации.
import { 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
- Псевдоним:
it.skip
Если вы хотите пропустить выполнение определенных тестов, но не хотите удалять код, вы можете использовать test.skip, чтобы исключить их из выполнения.
import { assert, test } from 'vitest';
test.skip('пропущенный тест', () => {
// Test skipped, no error
assert.equal(Math.sqrt(4), 3);
});Вы также можете пропустить тест динамически, вызвав skip в его контексте:
import { assert, test } from 'vitest';
test('пропущенный тест', context => {
context.skip();
// Test skipped, no error
assert.equal(Math.sqrt(4), 3);
});test.skipIf
- Псевдоним:
it.skipIf
В некоторых случаях вам может потребоваться запускать тесты в разных окружениях, и некоторые тесты могут быть специфичными для определенной среды. Вместо того, чтобы оборачивать тестовый код в if, вы можете использовать test.skipIf, чтобы пропустить тест, если условие истинно.
import { 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
- Псевдоним:
it.runIf
Противоположность test.skipIf.
import { 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
- Псевдоним:
it.only
Используйте test.only, чтобы запускать только определенные тесты в данном наборе. Это полезно для отладки.
При необходимости вы можете указать тайм-аут (в миллисекундах), чтобы ограничить время ожидания завершения теста. Значение по умолчанию — 5 секунд, и его можно настроить глобально с помощью testTimeout.
import { 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.tstest.concurrent
- Псевдоним:
it.concurrent
test.concurrent помечает тесты для параллельного выполнения. Он принимает имя теста, асинхронную функцию, содержащую тесты, и необязательный тайм-аут (в миллисекундах).
import { 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 работают с параллельными тестами. Допустимы следующие комбинации:
test.concurrent(/* ... */);
test.skip.concurrent(/* ... */); // или test.concurrent.skip(/* ... */)
test.only.concurrent(/* ... */); // или test.concurrent.only(/* ... */)
test.todo.concurrent(/* ... */); // или test.concurrent.todo(/* ... */)При выполнении параллельных тестов, для работы со снимками (Snapshots) и утверждениями (Assertions) необходимо использовать expect из локального Контекста теста. Это необходимо для того, чтобы убедиться, что обнаружен правильный тест.
test.concurrent('test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test.concurrent('test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});WARNING
Вы не можете использовать этот синтаксис, если Vitest используется для проверки типов.
test.sequential
- Псевдоним:
it.sequential
test.sequential помечает тест как последовательный. Это полезно, если вы хотите запускать тесты последовательно в describe.concurrent или с помощью опции командной строки --sequence.concurrent.
import { describe, test } from 'vitest';
// с опцией конфигурации { sequence: { concurrent: true } }
test('concurrent test 1', async () => {
/* ... */
});
test('concurrent test 2', async () => {
/* ... */
});
test.sequential('sequential test 1', async () => {
/* ... */
});
test.sequential('sequential test 2', async () => {
/* ... */
});
// внутри параллельного набора тестов
describe.concurrent('suite', () => {
test('concurrent test 1', async () => {
/* ... */
});
test('concurrent test 2', async () => {
/* ... */
});
test.sequential('sequential test 1', async () => {
/* ... */
});
test.sequential('sequential test 2', async () => {
/* ... */
});
});test.todo
- Псевдоним:
it.todo
Используйте test.todo, чтобы пометить тесты, которые будут реализованы позже. В отчете будет отображена запись для этих тестов, чтобы вы знали, сколько тестов вам еще предстоит реализовать.
// An entry will be shown in the report for this test
test.todo('нереализованный тест');test.fails
- Псевдоним:
it.fails
Используйте test.fails, чтобы указать, что тест должен завершиться с ошибкой.
import { 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
- Псевдоним:
it.each
TIP
Хотя test.each предоставляется для совместимости с Jest, Vitest также имеет test.for с дополнительной функцией для интеграции TestContext.
Используйте 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 ('%') (одиночный знак процента ('%'))
import { expect, test } from 'vitest';
test.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Вы также можете получить доступ к свойствам объекта с префиксом $, если вы используете объекты в качестве аргументов:
test.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Вы также можете получить доступ к атрибутам объекта с помощью ., если вы используете объекты в качестве аргументов:
test.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}.
import { expect, test } from 'vitest';
test.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);
});TIP
Vitest обрабатывает $values с помощью метода format chai. Если значение усекается, вы можете увеличить chaiConfig.truncateThreshold в файле конфигурации.
WARNING
Вы не можете использовать этот синтаксис, если Vitest используется для проверки типов.
test.for
- Псевдоним:
it.for
Альтернатива test.each для предоставления TestContext.
Отличие от test.each заключается в способе передачи массива в аргументы. Другие случаи, не являющиеся массивами (включая использование шаблонных строк), работают точно так же.
// `each` разворачивает массив
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// `for` не разворачивает массив
test.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => {
expect(a + b).toBe(expected);
});Второй аргумент — это TestContext, и его можно использовать для параллельных снимков, например:
test.concurrent.for([
[1, 1],
[1, 2],
[2, 1],
])('add(%i, %i)', ([a, b], { expect }) => {
expect(a + b).matchSnapshot();
});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;
/**
* Выбросить ошибку, если задача завершится с ошибкой (события не будут работать, если истинно)
*/
throws?: boolean;
/**
* Время на разогрев (в миллисекундах).
* @default 100ms
*/
warmupTime?: number;
/**
* Итерации прогрева.
* @default 5
*/
warmupIterations?: number;
/**
* Функция настройки для запуска перед каждой задачей бенчмарка (циклом).
*/
setup?: Hook;
/**
* Функция завершения для запуска после каждой задачи бенчмарка (цикла).
*/
teardown?: Hook;
}После выполнения тестового примера информация о структуре вывода выглядит следующим образом:
name hz min max mean p75 p99 p995 p999 rme samples
· normal sorting 6,526,368.12 0.0001 0.3638 0.0002 0.0002 0.0002 0.0002 0.0004 ±1.41% 652638export interface TaskResult {
/*
* последняя ошибка, которая была выброшена во время выполнения задачи
*/
error?: unknown;
/**
* Количество времени в миллисекундах для выполнения задачи бенчмарка (цикла).
*/
totalTime: number;
/**
* минимальное значение в выборках
*/
min: number;
/**
* максимальное значение в выборках
*/
max: number;
/**
* количество операций в секунду
*/
hz: number;
/**
* сколько времени занимает каждая операция (мс)
*/
period: number;
/**
* выборки задачи времени каждой итерации задачи (мс)
*/
samples: number[];
/**
* среднее/среднее выборок (оценка среднего генеральной совокупности)
*/
mean: number;
/**
* дисперсия выборок (оценка дисперсии генеральной совокупности)
*/
variance: number;
/**
* стандартное отклонение выборок (оценка стандартного отклонения генеральной совокупности)
*/
sd: number;
/**
* стандартная ошибка средней (известная как стандартное отклонение выборочного распределения выборочной средней)
*/
sem: number;
/**
* степени свободы
*/
df: number;
/**
* критическое значение выборок
*/
critical: number;
/**
* поле ошибки
*/
moe: number;
/**
* относительное поле ошибки
*/
rme: number;
/**
* медианное абсолютное отклонение
*/
mad: number;
/**
* p50/медианный перцентиль
*/
p50: number;
/**
* перцентиль p75
*/
p75: number;
/**
* перцентиль p99
*/
p99: number;
/**
* перцентиль p995
*/
p995: number;
/**
* перцентиль p999
*/
p999: number;
}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: number | string) {
if (typeof value !== 'number') {
throw new TypeError('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
- Alias:
suite.skip
Используйте describe.skip в тест-сьюте, чтобы пропустить выполнение определенного блока describe.
import { assert, describe, test } from 'vitest';
describe.skip('skipped suite', () => {
test('sqrt', () => {
// Suite skipped, no error
assert.equal(Math.sqrt(4), 3);
});
});describe.skipIf
- Alias:
suite.skipIf
В некоторых случаях вам может потребоваться запускать тест-сьюты несколько раз в разных окружениях, и некоторые из них могут быть специфичными для определенного окружения. Вместо того чтобы оборачивать тест-сьют в if, вы можете использовать describe.skipIf, чтобы пропустить набор, если условие истинно.
import { 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.runIf
- Псевдоним:
suite.runIf
Противоположность describe.skipIf.
import { assert, describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.runIf(isDev)('dev only test suite', () => {
// this test suite only runs in development
});WARNING
Вы не можете использовать этот синтаксис, когда используете Vitest как проверку типов.
describe.only
- Тип:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
Используйте describe.only, чтобы запускать только определенные тест-сьюты.
import { assert, describe, test } from 'vitest';
// 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.tsdescribe.concurrent
- Alias:
suite.concurrent
describe.concurrent выполняет все внутренние наборы тестов и тесты параллельно
import { describe, test } from 'vitest';
// Все наборы тестов и тесты внутри этого набора будут выполняться параллельно
describe.concurrent('suite', () => {
test('concurrent test 1', async () => {
/* ... */
});
describe('concurrent suite 2', async () => {
test('concurrent test inner 1', async () => {
/* ... */
});
test('concurrent test inner 2', async () => {
/* ... */
});
});
test.concurrent('concurrent test 3', async () => {
/* ... */
});
});.skip, .only и .todo работают с параллельными тест-сьютами. Все следующие комбинации являются допустимыми:
describe.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
- Alias:
suite.sequential
describe.sequential в тест-сьюте помечает каждый тест как последовательный. Это полезно, если требуется запускать тесты последовательно внутри describe.concurrent или при использовании опции командной строки --sequence.concurrent.
import { describe, test } from 'vitest';
describe.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
- Alias:
suite.shuffle
Vitest предоставляет способ запускать все тесты в случайном порядке с помощью флага CLI --sequence.shuffle или опции конфигурации sequence.shuffle, но если вы хотите, чтобы только часть тестов в вашем наборе запускалась в случайном порядке, вы можете отметить этот набор с помощью этого флага.
import { describe, test } from 'vitest';
describe.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
- Alias:
suite.todo
Используйте describe.todo, чтобы создать заготовки для тест-сьютов, которые будут реализованы позже. В отчете будет отображаться запись для этих тестов, чтобы вы знали, сколько тестов вам еще нужно реализовать.
// An entry will be shown in the report for this suite
describe.todo('unimplemented suite');describe.each
- Alias:
suite.each
Используйте describe.each, если у вас есть несколько тестов, которые зависят от одних и тех же данных.
import { describe, expect, test } from 'vitest';
describe.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}.
import { describe, expect, test } from 'vitest';
describe.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 секунд.
import { beforeEach } from 'vitest';
beforeEach(async () => {
// Clear mocks and add some testing data after before each test run
await stopMocking();
await addUser({ name: 'John' });
});Здесь beforeEach гарантирует, что пользователь будет добавлен перед каждым тестом.
beforeEach также принимает необязательную функцию очистки (cleanup function) (эквивалентную afterEach).
import { 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 секунд.
import { afterEach } from 'vitest';
afterEach(async () => {
await clearTestingData(); // clear testing data after each test run
});Здесь afterEach гарантирует, что тестовые данные будут очищены после каждого запуска теста.
TIP
В Vitest 1.3.0 добавлен хук onTestFinished. Вы можете вызвать его во время выполнения теста, чтобы очистить любое состояние после завершения теста.
beforeAll
- Тип:
beforeAll(fn: () => Awaitable<void>, timeout?: number)
Регистрирует обратный вызов, который будет вызван один раз перед началом запуска всех тестов в текущем контексте. Если функция возвращает промис, Vitest ждет, пока промис не будет разрешен, прежде чем запускать тесты.
При необходимости вы можете указать тайм-аут (в миллисекундах) для указания, как долго ждать перед завершением. Значение по умолчанию - 5 секунд.
import { beforeAll } from 'vitest';
beforeAll(async () => {
await startMocking(); // called once before all tests run
});Здесь beforeAll гарантирует, что mock-данные будут настроены перед запуском тестов.
beforeAll также принимает необязательную функцию очистки (cleanup function) (эквивалентную afterAll).
import { 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 секунд.
import { afterAll } from 'vitest';
afterAll(async () => {
await stopMocking(); // this method is called after all tests run
});Здесь afterAll гарантирует, что метод stopMocking будет вызван после запуска всех тестов.
Хуки Теста
Vitest предоставляет несколько хуков, которые можно вызывать во время выполнения теста для очистки состояния после завершения теста.
WARNING
Эти хуки вызовут ошибку, если они вызываются вне тела теста.
onTestFinished
Этот хук всегда вызывается после завершения выполнения теста. Он вызывается после хуков afterEach, так как они могут повлиять на результат теста. Он получает объект TaskResult с текущим результатом теста.
import { onTestFinished, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});WARNING
Если вы запускаете тесты параллельно, вам всегда следует использовать хук onTestFinished из контекста теста, поскольку Vitest не отслеживает параллельные тесты в глобальных хуках:
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFinished }) => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});Этот хук особенно полезен при создании повторно используемой логики:
// Это может быть в отдельном файле
function getTestDb() {
const db = connectMockedDb();
onTestFinished(() => db.close());
return db;
}
test('performs a user query', async () => {
const db = getTestDb();
expect(await db.query('SELECT * from users').perform()).toEqual([]);
});
test('performs an organization query', async () => {
const db = getTestDb();
expect(await db.query('SELECT * from organizations').perform()).toEqual([]);
});TIP
Этот хук всегда вызывается в обратном порядке и не зависит от параметра sequence.hooks.
onTestFailed
Этот хук вызывается только после того, как тест завершился неудачей. Он вызывается после хуков afterEach, так как они могут повлиять на результат теста. Он получает объект TaskResult с текущим результатом теста. Этот хук полезен для отладки.
import { onTestFailed, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFailed(e => {
console.log(e.result.errors);
});
db.query('SELECT * FROM users');
});WARNING
Если вы запускаете тесты параллельно, вам всегда следует использовать хук onTestFailed из контекста теста, поскольку Vitest не отслеживает параллельные тесты в глобальных хуках:
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFailed }) => {
const db = connectDb();
onTestFailed(result => {
console.log(result.errors);
});
db.query('SELECT * FROM users');
});