Referência da API de Teste
Os seguintes tipos são usados nas assinaturas de tipo abaixo.
type Awaitable<T> = T | PromiseLike<T>;
type TestFunction = () => Awaitable<void>;
interface TestOptions {
/**
* O teste falhará se demorar muito para ser executado.
*/
timeout?: number;
/**
* Tenta executar o teste novamente um número específico de vezes se ele falhar.
*
* @default 0
*/
retry?: number;
/**
* Repete o mesmo teste várias vezes, mesmo que ele falhe em cada tentativa.
* Se a opção "retry" estiver ativada e o teste falhar, ele usará todas as tentativas em cada ciclo de repetição.
* Útil para depurar falhas intermitentes.
*
* @default 0
*/
repeats?: number;
}Quando uma função de teste retorna uma promessa, o executor aguardará sua resolução para coletar as asserções assíncronas. Se a promessa for rejeitada, o teste falhará.
TIP
No Jest, TestFunction também pode ser do tipo (done: DoneCallback) => void. Se esta forma for usada, o teste não será concluído até que done seja chamado. Você pode obter o mesmo comportamento usando uma função async. Para mais detalhes, consulte a seção Done Callback do guia de Migração.
Você pode definir opções encadeando propriedades a uma função:
import { test } from 'vitest';
test.skip('skipped test', () => {
// alguma lógica que falha agora
});
test.concurrent.skip('skipped concurrent test', () => {
// alguma lógica que falha agora
});Alternativamente, você também pode fornecer um objeto como segundo argumento:
import { test } from 'vitest';
test('skipped test', { skip: true }, () => {
// alguma lógica que falha agora
});
test('skipped concurrent test', { skip: true, concurrent: true }, () => {
// alguma lógica que falha agora
});Ambas as abordagens funcionam exatamente da mesma maneira. A escolha entre uma e outra é puramente estilística.
Observe que, se você fornecer o tempo limite como último argumento, não poderá mais usar as opções:
import { test } from 'vitest';
// ✅ isso funciona
test.skip('heavy test', () => {
// ...
}, 10_000);
// ❌ isso não funciona
test(
'heavy test',
{ skip: true },
() => {
// ...
},
10_000
);No entanto, você pode fornecer um tempo limite dentro do objeto de opções:
import { test } from 'vitest';
// ✅ isso funciona
test('heavy test', { skip: true, timeout: 10_000 }, () => {
// ...
});test
- Alias:
it
test define um conjunto de asserções relacionadas. Ele recebe o nome do teste e uma função que encapsula as asserções a serem verificadas.
Opcionalmente, você pode fornecer um tempo limite (em milissegundos) para especificar quanto tempo esperar antes de terminar. O padrão é 5 segundos e pode ser configurado globalmente com testTimeout.
import { expect, test } from 'vitest';
test('should work as expected', () => {
expect(Math.sqrt(4)).toBe(2);
});test.extend
- Alias:
it.extend
Use test.extend para estender o contexto de teste com fixtures personalizadas. Isso retornará um novo test que também é extensível, permitindo que você componha mais fixtures ou sobrescreva as existentes conforme sua necessidade. Veja Estender Contexto de Teste para mais informações.
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
- Alias:
it.skip
Se você quiser pular a execução de certos testes, mas não quiser excluir o código por algum motivo, você pode usar test.skip para evitar executá-los.
import { assert, test } from 'vitest';
test.skip('skipped test', () => {
// Teste ignorado, sem erro
assert.equal(Math.sqrt(4), 3);
});Você também pode pular um teste chamando skip em seu contexto dinamicamente:
import { assert, test } from 'vitest';
test('skipped test', context => {
context.skip();
// Teste ignorado, sem erro
assert.equal(Math.sqrt(4), 3);
});Desde o Vitest 3.1, se a condição for desconhecida, você pode fornecê-la ao método skip como o primeiro argumento:
import { assert, test } from 'vitest';
test('skipped test', context => {
context.skip(Math.random() < 0.5, 'optional message');
// Teste ignorado, sem erro
assert.equal(Math.sqrt(4), 3);
});test.skipIf
- Alias:
it.skipIf
Em alguns casos, você pode executar testes várias vezes em ambientes diferentes, e alguns testes podem ser específicos do ambiente. Em vez de envolver o código do teste com um if, você pode usar test.skipIf para pular o teste sempre que a condição for truthy.
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.skipIf(isDev)('prod only test', () => {
// este teste só é executado em produção
});WARNING
Esta sintaxe não pode ser usada ao utilizar o Vitest como verificador de tipo.
test.runIf
- Alias:
it.runIf
O oposto de test.skipIf.
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.runIf(isDev)('dev only test', () => {
// este teste só é executado em desenvolvimento
});WARNING
Esta sintaxe não pode ser usada ao utilizar o Vitest como verificador de tipo.
test.only
- Alias:
it.only
Use test.only para executar apenas testes específicos em um determinado conjunto. Isso é útil para depuração.
Opcionalmente, você pode fornecer um tempo limite (em milissegundos) para especificar quanto tempo esperar antes de terminar. O padrão é 5 segundos e pode ser configurado globalmente com testTimeout.
import { assert, test } from 'vitest';
test.only('test', () => {
// Apenas este teste (e outros marcados com only) são executados
assert.equal(Math.sqrt(4), 2);
});Às vezes, é muito útil executar testes only em um determinado arquivo, ignorando todos os outros testes de todo o conjunto de testes, que poluem a saída.
Para fazer isso, execute vitest com o arquivo específico contendo os testes em questão.
# vitest interesting.test.tstest.concurrent
- Alias:
it.concurrent
test.concurrent marca testes para serem executados em paralelo. Ele recebe o nome do teste, uma função assíncrona que contém os testes a serem executados e um tempo limite opcional (em milissegundos).
import { describe, test } from 'vitest';
// Os dois testes marcados com concurrent serão executados em paralelo
describe('suite', () => {
test('serial test', async () => {
/* ... */
});
test.concurrent('concurrent test 1', async () => {
/* ... */
});
test.concurrent('concurrent test 2', async () => {
/* ... */
});
});test.skip, test.only e test.todo funcionam com testes concorrentes. Todas as combinações a seguir são válidas:
test.concurrent(/* ... */);
test.skip.concurrent(/* ... */); // ou test.concurrent.skip(/* ... */)
test.only.concurrent(/* ... */); // ou test.concurrent.only(/* ... */)
test.todo.concurrent(/* ... */); // ou test.concurrent.todo(/* ... */)Ao executar testes concorrentes, Snapshots e Asserções devem usar expect do Contexto de Teste local para garantir que o teste correto seja detectado.
test.concurrent('test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test.concurrent('test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});WARNING
Esta sintaxe não pode ser usada ao utilizar o Vitest como verificador de tipo.
test.sequential
- Alias:
it.sequential
test.sequential marca um teste como sequencial. Isso é útil se você quiser executar testes sequencialmente dentro de describe.concurrent ou com a opção de comando --sequence.concurrent.
import { describe, test } from 'vitest';
// com a opção de configuração { 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 () => {
/* ... */
});
// dentro de um conjunto concorrente
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
- Alias:
it.todo
Use test.todo para marcar testes a serem implementados posteriormente. Uma entrada será exibida no relatório para esses testes, informando quantos ainda precisam ser implementados.
// Uma entrada será mostrada no relatório para este teste
test.todo('unimplemented test');test.fails
- Alias:
it.fails
Use test.fails para indicar que uma asserção deve falhar explicitamente.
import { expect, test } from 'vitest';
function myAsyncFunc() {
return new Promise(resolve => resolve(1));
}
test.fails('fail test', async () => {
await expect(myAsyncFunc()).rejects.toBe(1);
});WARNING
Esta sintaxe não pode ser usada ao utilizar o Vitest como verificador de tipo.
test.each
- Alias:
it.each
TIP
Embora test.each seja fornecido para compatibilidade com Jest, o Vitest também possui test.for com um recurso adicional para integrar TestContext.
Use test.each quando precisar executar o mesmo teste com variáveis diferentes. Você pode injetar parâmetros usando a formatação printf no nome do teste, seguindo a ordem dos parâmetros da função de teste.
%s: string%d: number%i: integer%f: floating point value%j: json%o: object%#: índice baseado em 0 do caso de teste%$: índice baseado em 1 do caso de teste%%: um único sinal de porcentagem ('%')
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);
});
// o resultado será
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3Você também pode acessar propriedades de objeto e elementos de array com o prefixo $:
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);
});
// o resultado será
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add($0, $1) -> $2', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// o resultado será
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3Você também pode acessar atributos de objetos com ., se estiver usando objetos como argumentos:
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);
});
// o resultado será
// ✓ add(1, b) -> 1b
// ✓ add(2, b) -> 2b
// ✓ add(3, b) -> 3bA partir do Vitest 0.25.3, você também pode usar a sintaxe de template string para tabelas.
- A primeira linha deve ser os nomes das colunas, separados por
|; - Uma ou mais linhas subsequentes de dados fornecidos como expressões literais de modelo usando a sintaxe
${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
O Vitest processa $values com o método format do Chai. Se o valor estiver excessivamente truncado, você pode aumentar chaiConfig.truncateThreshold em seu arquivo de configuração.
WARNING
Esta sintaxe não pode ser usada ao utilizar o Vitest como verificador de tipo.
test.for
- Alias:
it.for
Alternativa a test.each para fornecer TestContext.
A diferença em relação a test.each está na forma como os arrays são fornecidos nos argumentos. Argumentos que não são arrays para test.for (incluindo o uso de template strings) funcionam exatamente da mesma forma que para test.each.
// `each` espalha o caso de array
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// `for` não espalha o caso de array (observe os colchetes em torno dos argumentos)
test.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => {
expect(a + b).toBe(expected);
});O 2º argumento é TestContext e pode ser usado para snapshots concorrentes, por exemplo:
test.concurrent.for([
[1, 1],
[1, 2],
[2, 1],
])('add(%i, %i)', ([a, b], { expect }) => {
expect(a + b).matchSnapshot();
});bench
- Tipo:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
bench define um benchmark. Em termos do Vitest, um benchmark é uma função que define uma série de operações. O Vitest executa esta função várias vezes para exibir diferentes resultados de desempenho.
O Vitest usa a biblioteca tinybench internamente, herdando todas as suas opções que podem ser usadas como terceiro argumento.
import { bench } from 'vitest';
bench(
'normal sorting',
() => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
},
{ time: 1000 }
);export interface Options {
/**
* Tempo necessário para a execução de uma tarefa de benchmark (em milissegundos).
* @default 500
*/
time?: number;
/**
* Número de vezes que uma tarefa deve ser executada, mesmo que a opção de tempo tenha sido atingida.
* @default 10
*/
iterations?: number;
/**
* Função para obter o *timestamp* atual em milissegundos.
*/
now?: () => number;
/**
* Um AbortSignal para abortar o benchmark.
*/
signal?: AbortSignal;
/**
* Lança um erro se uma tarefa falhar (eventos não funcionarão se esta opção for true).
*/
throws?: boolean;
/**
* Tempo de aquecimento (em milissegundos).
* @default 100ms
*/
warmupTime?: number;
/**
* Iterações de aquecimento.
* @default 5
*/
warmupIterations?: number;
/**
* Função de configuração a ser executada antes de cada tarefa de benchmark (ciclo).
*/
setup?: Hook;
/**
* Função de *teardown* (finalização) a ser executada após cada tarefa de benchmark (ciclo).
*/
teardown?: Hook;
}Após a execução do caso de teste, as informações da estrutura de saída são as seguintes:
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 {
/*
* o último erro que ocorreu durante a execução da tarefa
*/
error?: unknown;
/**
* O tempo total (em milissegundos) para executar a tarefa de benchmark (ciclo).
*/
totalTime: number;
/**
* o valor mínimo das amostras
*/
min: number;
/**
* o valor máximo das amostras
*/
max: number;
/**
* o número de operações por segundo
*/
hz: number;
/**
* Duração de cada operação (em ms)
*/
period: number;
/**
* Amostras do tempo de cada iteração da tarefa (em ms)
*/
samples: number[];
/**
* Média das amostras (estimativa da média da população)
*/
mean: number;
/**
* Variância das amostras (estimativa da variância populacional)
*/
variance: number;
/**
* Desvio padrão das amostras (estimativa do desvio padrão populacional)
*/
sd: number;
/**
* Erro padrão da média (também conhecido como o desvio padrão da distribuição amostral da média da amostra)
*/
sem: number;
/**
* graus de liberdade
*/
df: number;
/**
* Valor crítico das amostras
*/
critical: number;
/**
* Margem de erro
*/
moe: number;
/**
* Margem de erro relativa
*/
rme: number;
/**
* Desvio absoluto mediano
*/
mad: number;
/**
* Percentil p50 (mediana)
*/
p50: number;
/**
* percentil p75
*/
p75: number;
/**
* percentil p99
*/
p99: number;
/**
* percentil p995
*/
p995: number;
/**
* percentil p999
*/
p999: number;
}bench.skip
- Tipo:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
Você pode usar a sintaxe bench.skip para pular a execução de benchmarks específicos.
import { bench } from 'vitest';
bench.skip('normal sorting', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});bench.only
- Tipo:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
Use bench.only para executar apenas benchmarks específicos em um determinado conjunto. Isso é útil durante a depuração.
import { bench } from 'vitest';
bench.only('normal sorting', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});bench.todo
- Tipo:
(name: string | Function) => void
Use bench.todo para marcar benchmarks a serem implementados posteriormente.
import { bench } from 'vitest';
bench.todo('unimplemented test');describe
Quando você usa test ou bench no nível superior de um arquivo, eles são coletados como parte do conjunto implícito para ele. Usando describe, você pode definir um novo conjunto no contexto atual, como um conjunto de testes ou benchmarks relacionados e outros conjuntos aninhados. Um conjunto permite que você organize seus testes e benchmarks para que os relatórios fiquem mais claros.
// basic.spec.ts
// organizando testes
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
// organizando 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;
});
});
});Você também pode aninhar blocos describe se tiver uma hierarquia de testes ou benchmarks:
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
- Pseudônimo:
suite.skip
Use describe.skip em um conjunto para evitar executar um bloco describe específico.
import { assert, describe, test } from 'vitest';
describe.skip('skipped suite', () => {
test('sqrt', () => {
// Suite ignorada, sem erro
assert.equal(Math.sqrt(4), 3);
});
});describe.skipIf
- Pseudônimo:
suite.skipIf
Em alguns casos, você pode executar conjuntos várias vezes com ambientes diferentes, e alguns dos conjuntos podem ser específicos do ambiente. Em vez de envolver o conjunto com if, você pode usar describe.skipIf para ignorar o conjunto sempre que a condição for verdadeira.
import { describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.skipIf(isDev)('prod only test suite', () => {
// esta suite de testes só roda em produção
});WARNING
Você não pode usar esta sintaxe ao usar o Vitest como verificador de tipo.
describe.runIf
- Pseudônimo:
suite.runIf
O oposto de describe.skipIf.
import { assert, describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.runIf(isDev)('dev only test suite', () => {
// esta suite de testes só roda em desenvolvimento
});WARNING
Você não pode usar esta sintaxe ao usar o Vitest como verificador de tipo.
describe.only
- Tipo:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
Use describe.only para executar apenas certos conjuntos.
import { assert, describe, test } from 'vitest';
// Apenas esta suite (e outras marcadas com only) são executadas
describe.only('suite', () => {
test('sqrt', () => {
assert.equal(Math.sqrt(4), 3);
});
});
describe('other suite', () => {
// ... será ignorada
});Às vezes, é muito útil executar testes only em um determinado arquivo, ignorando todos os outros testes da suite de testes inteira, o que polui a saída.
Para fazer isso, execute vitest com o arquivo específico que contém os testes em questão.
# vitest interesting.test.tsdescribe.concurrent
- Pseudônimo:
suite.concurrent
describe.concurrent executa todos os conjuntos internos e testes em paralelo.
import { describe, test } from 'vitest';
// Todos os conjuntos e testes dentro deste conjunto serão executados em paralelo
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 e .todo funcionam com conjuntos concorrentes. Todas as seguintes combinações são válidas:
describe.concurrent(/* ... */);
describe.skip.concurrent(/* ... */); // ou describe.concurrent.skip(/* ... */)
describe.only.concurrent(/* ... */); // ou describe.concurrent.only(/* ... */)
describe.todo.concurrent(/* ... */); // ou describe.concurrent.todo(/* ... */)Ao executar testes concorrentes, Snapshots e Assertions devem usar expect do Contexto de Teste local para garantir que o teste correto seja detectado.
describe.concurrent('suite', () => {
test('concurrent test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test('concurrent test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
});WARNING
Você não pode usar esta sintaxe ao usar o Vitest como verificador de tipo.
describe.sequential
- Pseudônimo:
suite.sequential
describe.sequential em um conjunto marca cada teste como sequencial. Isso é útil se você deseja executar testes em sequência dentro de describe.concurrent ou com a opção de comando --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
- Pseudônimo:
suite.shuffle
O Vitest oferece uma maneira de executar todos os testes em ordem aleatória através da flag CLI --sequence.shuffle ou da opção de configuração sequence.shuffle, mas se você quiser ter apenas uma parte da sua suite de testes para executar testes em ordem aleatória, você pode marcá-la com essa flag.
import { describe, test } from 'vitest';
// ou describe('suite', { shuffle: true }, ...)
describe.shuffle('suite', () => {
test('random test 1', async () => {
/* ... */
});
test('random test 2', async () => {
/* ... */
});
test('random test 3', async () => {
/* ... */
});
// `shuffle` é herdado
describe('still random', () => {
test('random 4.1', async () => {
/* ... */
});
test('random 4.2', async () => {
/* ... */
});
});
// desativa shuffle dentro
describe('not random', { shuffle: false }, () => {
test('in order 5.1', async () => {
/* ... */
});
test('in order 5.2', async () => {
/* ... */
});
});
});
// a ordem depende da opção sequence.seed na configuração (Date.now() por padrão).skip, .only e .todo funcionam com conjuntos aleatórios.
WARNING
Você não pode usar esta sintaxe ao usar o Vitest como verificador de tipo.
describe.todo
- Pseudônimo:
suite.todo
Use describe.todo para criar stubs de conjuntos a serem implementados posteriormente. Uma entrada será exibida no relatório para os testes, para que você saiba quantos testes ainda precisa implementar.
// Uma entrada será exibida no relatório para esta suite
describe.todo('unimplemented suite');describe.each
- Pseudônimo:
suite.each
TIP
Enquanto describe.each é fornecido para compatibilidade com Jest, o Vitest também possui describe.for, que simplifica os tipos de argumento e se alinha com test.for.
Use describe.each se você tiver mais de um teste que depende dos mesmos dados.
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);
});
});A partir do Vitest 0.25.3, você também pode usar a sintaxe de tabela em template strings.
- A primeira linha deve ser os nomes das colunas, separados por
|; - Uma ou mais linhas subsequentes de dados fornecidos como expressões de template literal usando a sintaxe `${valor}}$.
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
Você não pode usar esta sintaxe ao usar o Vitest como verificador de tipo.
describe.for
- Pseudônimo:
suite.for
A diferença de describe.each é como o caso de array é fornecido nos argumentos. Outros casos que não sejam de array (incluindo o uso de template string) funcionam exatamente da mesma forma.
// `each` espalha o caso de array
describe.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
test('test', () => {
expect(a + b).toBe(expected);
});
});
// `for` não espalha o caso de array
describe.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => {
test('test', () => {
expect(a + b).toBe(expected);
});
});Configuração e Desmontagem
Essas funções permitem que você se engaje no ciclo de vida dos testes para evitar a repetição de código de configuração e finalização. Elas se aplicam ao contexto atual: o arquivo, se usadas no nível superior, ou o conjunto de testes (suite) atual, se estiverem dentro de um bloco describe. Esses hooks não são chamados quando você está executando o Vitest como um verificador de tipo.
beforeEach
- Tipo:
beforeEach(fn: () => Awaitable<void>, timeout?: number)
Registra uma função de callback a ser chamada antes da execução de cada teste no contexto atual. Se a função retornar uma promessa, o Vitest aguardará a resolução da promessa antes de executar o teste.
Opcionalmente, você pode passar um tempo limite (em milissegundos) definindo quanto tempo esperar antes de terminar. O padrão é 5 segundos.
import { beforeEach } from 'vitest';
beforeEach(async () => {
// Limpa mocks e adiciona alguns dados de teste antes de cada execução de teste
await stopMocking();
await addUser({ name: 'John' });
});Aqui, o beforeEach garante que um usuário seja adicionado para cada teste.
O beforeEach também aceita uma função de limpeza opcional (equivalente a afterEach).
import { beforeEach } from 'vitest';
beforeEach(async () => {
// chamado uma vez antes de cada execução de teste
await prepareSomething();
// função de limpeza, chamada uma vez após cada execução de teste
return async () => {
await resetSomething();
};
});afterEach
- Tipo:
afterEach(fn: () => Awaitable<void>, timeout?: number)
Registra uma função de callback a ser chamada após a conclusão de cada teste no contexto atual. Se a função retornar uma promessa, o Vitest aguarda até que a promessa seja resolvida antes de continuar.
Opcionalmente, você pode fornecer um tempo limite (em milissegundos) para especificar quanto tempo esperar antes de terminar. O padrão é 5 segundos.
import { afterEach } from 'vitest';
afterEach(async () => {
await clearTestingData(); // limpa os dados de teste após cada execução de teste
});Aqui, o afterEach garante que os dados de teste sejam limpos após cada execução de teste.
TIP
O Vitest 1.3.0 adicionou o hook onTestFinished. Você pode chamá-lo durante a execução do teste para limpar qualquer estado após a conclusão do teste.
beforeAll
- Tipo:
beforeAll(fn: () => Awaitable<void>, timeout?: number)
Registra uma função de callback a ser chamada uma vez antes de iniciar a execução de todos os testes no contexto atual. Se a função retornar uma promessa, o Vitest aguardará a resolução da promessa antes de executar os testes.
Opcionalmente, você pode fornecer um tempo limite (em milissegundos) para especificar quanto tempo esperar antes de terminar. O padrão é 5 segundos.
import { beforeAll } from 'vitest';
beforeAll(async () => {
await startMocking(); // chamado uma vez antes de todos os testes serem executados
});Aqui, o beforeAll garante que os dados mock sejam configurados antes da execução dos testes.
beforeAll também aceita uma função de limpeza opcional (equivalente a afterAll).
import { beforeAll } from 'vitest';
beforeAll(async () => {
// chamado uma vez antes de todos os testes serem executados
await startMocking();
// função de limpeza, chamada uma vez após todos os testes serem executados
return async () => {
await stopMocking();
};
});afterAll
- Tipo:
afterAll(fn: () => Awaitable<void>, timeout?: number)
Registra uma função de callback a ser chamada uma vez após a execução de todos os testes no contexto atual. Se a função retornar uma promessa, o Vitest aguardará a resolução da promessa antes de continuar.
Opcionalmente, você pode fornecer um tempo limite (em milissegundos) para especificar quanto tempo esperar antes de terminar. O padrão é 5 segundos.
import { afterAll } from 'vitest';
afterAll(async () => {
await stopMocking(); // este método é chamado após todos os testes serem executados
});Aqui, o afterAll garante que o método stopMocking seja chamado após a execução de todos os testes.
Hooks de Teste
O Vitest fornece alguns hooks que você pode chamar durante a execução do teste para limpar o estado após a conclusão do teste.
WARNING
Esses hooks resultarão em um erro se forem chamados fora do corpo do teste.
onTestFinished
Este hook é sempre chamado após a conclusão do teste. Ele é chamado depois dos hooks afterEach, pois estes podem influenciar o resultado do teste. Ele recebe um objeto ExtendedContext, assim como beforeEach e afterEach.
import { onTestFinished, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});WARNING
Se você estiver executando testes em concorrência, você deve sempre usar o hook onTestFinished do contexto de teste, pois o Vitest não rastreia testes concorrentes em hooks globais:
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFinished }) => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});Este hook é particularmente útil ao criar lógica reutilizável:
// isso pode estar em um arquivo separado
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
Este hook é sempre chamado em ordem inversa e não é afetado pela opção sequence.hooks.
onTestFailed
Este hook é chamado apenas após o teste falhar. Ele é chamado depois dos hooks afterEach, pois estes podem influenciar o resultado do teste. Ele recebe um objeto ExtendedContext, assim como beforeEach e afterEach. Este hook é útil para depuração.
import { onTestFailed, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFailed(({ task }) => {
console.log(task.result.errors);
});
db.query('SELECT * FROM users');
});WARNING
Se você estiver executando testes em concorrência, você deve sempre usar o hook onTestFailed do contexto de teste, pois o Vitest não rastreia testes concorrentes em hooks globais:
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFailed }) => {
const db = connectDb();
onTestFailed(({ task }) => {
console.log(task.result.errors);
});
db.query('SELECT * FROM users');
});