Контекст теста
Контекст теста Vitest, вдохновленный Playwright Fixtures, позволяет определять утилиты, состояния и фикстуры, используемые в тестах.
Использование
Контекст теста передается первым аргументом в каждый обработчик теста.
import { it } from 'vitest';
it('should work', ctx => {
// выводит имя теста
console.log(ctx.task.name);
});
Встроенный контекст теста
context.task
Объект только для чтения, содержащий метаданные текущего теста.
context.expect
API expect
, привязанный к текущему тесту:
import { it } from 'vitest';
it('math is easy', ({ expect }) => {
expect(2 + 2).toBe(4);
});
Этот API полезен при параллельном запуске snapshot-тестов, поскольку глобальный expect
не может корректно отслеживать их:
import { it } from 'vitest';
it.concurrent('math is easy', ({ expect }) => {
expect(2 + 2).toMatchInlineSnapshot();
});
it.concurrent('math is hard', ({ expect }) => {
expect(2 * 2).toMatchInlineSnapshot();
});
context.skip
Пропускает выполнение текущего теста и помечает его как пропущенный (skipped):
import { expect, it } from 'vitest';
it('math is hard', ({ skip }) => {
skip();
expect(2 + 2).toBe(5);
});
Расширение контекста теста
Vitest предоставляет два способа расширения контекста теста.
test.extend
Как и в Playwright, вы можете использовать этот метод для определения собственного API test
с пользовательскими фикстурами и повторно использовать его в любом месте.
Например, создадим myTest
с двумя фикстурами: todos
и archive
.
// my-test.ts
import { test } from 'vitest';
const todos = [];
const archive = [];
export const myTest = test.extend({
todos: async ({}, use) => {
// настройка фикстуры перед каждым тестом
todos.push(1, 2, 3);
// использование значения фикстуры
await use(todos);
// очистка фикстуры после каждого теста
todos.length = 0;
},
archive,
});
Затем мы можем импортировать и использовать его.
import { expect } from 'vitest';
import { myTest } from './my-test.js';
myTest('add items to todos', ({ todos }) => {
expect(todos.length).toBe(3);
todos.push(4);
expect(todos.length).toBe(4);
});
myTest('move items from todos to archive', ({ todos, archive }) => {
expect(todos.length).toBe(3);
expect(archive.length).toBe(0);
archive.push(todos.pop());
expect(todos.length).toBe(2);
expect(archive.length).toBe(1);
});
Мы также можем добавить больше фикстур или переопределить существующие, расширив myTest
.
export const myTest2 = myTest.extend({
settings: {
// ...
},
});
Инициализация фикстур
Vitest автоматически инициализирует фикстуры и внедряет их в контекст теста, основываясь на их использовании.
import { test } from 'vitest';
async function todosFn({ task }, use) {
await use([1, 2, 3]);
}
const myTest = test.extend({
todos: todosFn,
archive: [],
});
// todosFn не будет запущена
myTest('', () => {});
myTest('', ({ archive }) => {});
// todosFn будет запущена
myTest('', ({ todos }) => {});
WARNING
При использовании test.extend()
с фикстурами рекомендуется использовать деструктуризацию { todos }
для доступа к контексту как в функции фикстуры, так и в функции теста.
Автоматические фикстуры
Vitest также поддерживает кортежную структуру для фикстур, позволяя вам передавать параметры для каждой фикстуры. Например, вы можете использовать ее для явной инициализации фикстуры, даже если она не используется в тестах.
import { test as base } from 'vitest';
const test = base.extend({
fixture: [
async ({}, use) => {
// Эта функция будет выполнена
setup();
await use();
teardown();
},
{ auto: true }, // Отметить как автоматическую фикстуру
],
});
test('', () => {});
TypeScript
Чтобы предоставить типы для ваших пользовательских фикстур, вы можете передать generic-тип в качестве аргумента.
interface MyFixtures {
todos: number[];
archive: number[];
}
const myTest = test.extend<MyFixtures>({
todos: [],
archive: [],
});
myTest('', context => {
expectTypeOf(context.todos).toEqualTypeOf<number[]>();
expectTypeOf(context.archive).toEqualTypeOf<number[]>();
});
beforeEach
и afterEach
Контексты различны для каждого теста. Вы можете получить доступ к ним и расширить их в хуках beforeEach
и afterEach
.
import { beforeEach, it } from 'vitest';
beforeEach(async context => {
// расширение контекста
context.foo = 'bar';
});
it('should work', ({ foo }) => {
console.log(foo); // 'bar'
});
TypeScript
Чтобы определить типы свойств для всех ваших пользовательских контекстов, вы можете расширить тип TestContext
, добавив следующее объявление:
declare module 'vitest' {
export interface TestContext {
foo?: string;
}
}
Если вы хотите предоставить типы свойств только для определенных хуков beforeEach
, afterEach
, it
и test
, вы можете передать тип в качестве generic-аргумента.
interface LocalTestContext {
foo: string;
}
beforeEach<LocalTestContext>(async context => {
// typeof context is 'TestContext & LocalTestContext'
context.foo = 'bar';
});
it<LocalTestContext>('should work', ({ foo }) => {
// typeof foo is 'string'
console.log(foo); // 'bar'
});