Contexto de Teste
Inspirado em Playwright Fixtures, o contexto de teste do Vitest permite que você defina utilidades, estados e fixtures que podem ser usados em seus testes.
Uso
O primeiro argumento para cada função de teste é um contexto de teste.
import { it } from 'vitest';
it('deve funcionar', ctx => {
// imprime o nome do teste
console.log(ctx.task.name);
});
Contexto de Teste Embutido
context.task
Um objeto somente leitura contendo metadados sobre o teste.
context.expect
A API expect
vinculada ao teste atual:
import { it } from 'vitest';
it('matemática é fácil', ({ expect }) => {
expect(2 + 2).toBe(4);
});
Esta API é útil para executar testes de snapshot em paralelo porque o expect
global não pode rastreá-los:
import { it } from 'vitest';
it.concurrent('matemática é fácil', ({ expect }) => {
expect(2 + 2).toMatchInlineSnapshot();
});
it.concurrent('matemática é difícil', ({ expect }) => {
expect(2 * 2).toMatchInlineSnapshot();
});
context.skip
Ignora a execução do teste subsequente e o marca como ignorado:
import { expect, it } from 'vitest';
it('matemática é difícil', ({ skip }) => {
skip();
expect(2 + 2).toBe(5);
});
Estender o Contexto de Teste
O Vitest oferece duas formas diferentes de estender o contexto de teste.
test.extend
WARNING
Esta API está disponível a partir do Vitest 0.32.3.
Como Playwright, você pode usar este método para definir sua própria API test
com fixtures personalizados e reutilizá-la em qualquer lugar.
Por exemplo, primeiro criamos myTest
com dois fixtures, todos
e archive
.
// my-test.ts
import { test } from 'vitest';
const todos = [];
const archive = [];
export const myTest = test.extend({
todos: async ({ task }, use) => {
// configura o fixture antes de cada função de teste
todos.push(1, 2, 3);
// usa o valor do fixture
await use(todos);
// limpa o fixture após cada função de teste
todos.length = 0;
},
archive,
});
Então podemos importar e usá-lo.
import { expect } from 'vitest';
import { myTest } from './my-test.ts';
myTest('adiciona itens a todos', ({ todos }) => {
expect(todos.length).toBe(3);
todos.add(4);
expect(todos.length).toBe(4);
});
myTest('move itens de todos para 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);
});
Também podemos adicionar mais fixtures ou substituir fixtures existentes estendendo myTest
.
export const myTest2 = myTest.extend({
settings: {
// ...
},
});
Inicialização de Fixture
O executor do Vitest irá inicializar de forma inteligente seus fixtures e os injetará no contexto de teste com base no uso.
import { test } from 'vitest';
async function todosFn({ task }, use) {
await use([1, 2, 3]);
}
const myTest = test.extend({
todos: todosFn,
archive: [],
});
// todosFn não será executado
myTest('', () => {});
myTest('', ({ archive }) => {});
// todosFn será executado
myTest('', ({ todos }) => {});
WARNING
Ao usar test.extend()
com fixtures, sempre use o padrão de desestruturação de objeto { todos }
para acessar o contexto tanto na função fixture quanto na função de teste.
TypeScript
Para definir os tipos de fixture para todos os seus contextos personalizados, você pode passar o tipo de fixture como um genérico.
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
e afterEach
Os contextos são diferentes para cada teste. Você pode acessar e estender nos hooks beforeEach
e afterEach
.
import { beforeEach, it } from 'vitest';
beforeEach(async context => {
// estende o contexto
context.foo = 'bar';
});
it('deve funcionar', ({ foo }) => {
console.log(foo); // 'bar'
});
TypeScript
Para fornecer tipos de propriedade a todos os seus contextos personalizados, você pode estender o tipo TestContext
adicionando:
declare module 'vitest' {
export interface TestContext {
foo?: string;
}
}
Se quiser definir tipos de propriedade apenas para hooks específicos beforeEach
, afterEach
, it
e test
, você pode passar o tipo como um genérico.
interface LocalTestContext {
foo: string;
}
beforeEach<LocalTestContext>(async context => {
// typeof context é 'TestContext & LocalTestContext'
context.foo = 'bar';
});
it<LocalTestContext>('deve funcionar', ({ foo }) => {
// typeof foo é 'string'
console.log(foo); // 'bar'
});