Riferimento API di test
I seguenti tipi sono utilizzati nelle firme dei tipi qui sotto.
type Awaitable<T> = T | PromiseLike<T>;
type TestFunction = () => Awaitable<void>;
interface TestOptions {
/**
* Il test fallirà se l'esecuzione supera il tempo limite specificato.
*/
timeout?: number;
/**
* Riprova il test un numero specifico di volte in caso di fallimento.
*
* @default 0
*/
retry?: number;
/**
* Ripete lo stesso test più volte, anche in caso di fallimento.
* Se l'opzione "retry" è attiva e il test fallisce, ogni tentativo verrà utilizzato in ogni ciclo di ripetizione.
* Utile per diagnosticare fallimenti intermittenti.
*
* @default 0
*/
repeats?: number;
}Quando una funzione di test restituisce una promise, il runner attenderà che questa sia risolta per raccogliere le aspettative asincrone. Se la promise viene rifiutata, il test fallirà.
TIP
In Jest, TestFunction può anche essere di tipo (done: DoneCallback) => void. Se si usa questa forma, il test non sarà concluso finché non viene chiamata done. Puoi ottenere lo stesso risultato usando una funzione async; per maggiori dettagli, consulta la sezione Callback Done della guida alla migrazione.
È possibile definire le opzioni concatenando i metodi a una funzione di test:
import { test } from 'vitest';
test.skip('skipped test', () => {
// logica che attualmente fallisce
});
test.concurrent.skip('skipped concurrent test', () => {
// logica che attualmente fallisce
});Tuttavia, è anche possibile fornire un oggetto di opzioni come secondo argomento:
import { test } from 'vitest';
test('skipped test', { skip: true }, () => {
// logica che attualmente fallisce
});
test('skipped concurrent test', { skip: true, concurrent: true }, () => {
// logica che attualmente fallisce
});Entrambe le sintassi funzionano esattamente allo stesso modo. La scelta tra l'una o l'altra è puramente stilistica.
Si noti che se si fornisce il timeout come ultimo argomento, non è più possibile utilizzare l'oggetto opzioni:
import { test } from 'vitest';
// ✅ Questo funziona
test.skip('heavy test', () => {
// ...
}, 10_000);
// ❌ Questo non funziona
test(
'heavy test',
{ skip: true },
() => {
// ...
},
10_000
);Tuttavia, è possibile fornire un timeout all'interno dell'oggetto opzioni:
import { test } from 'vitest';
// ✅ Questo funziona
test('heavy test', { skip: true, timeout: 10_000 }, () => {
// ...
});test
- Alias:
it
test definisce un insieme di aspettative correlate. Accetta il nome del test e una funzione che contiene le aspettative da verificare.
Opzionalmente, è possibile fornire un timeout (in millisecondi) per specificare il tempo massimo di attesa prima della terminazione. Il valore predefinito è 5 secondi e può essere configurato globalmente tramite testTimeout.
import { expect, test } from 'vitest';
test('should work as expected', () => {
expect(Math.sqrt(4)).toBe(2);
});test.extend
- Alias:
it.extend
Utilizzare test.extend per estendere il contesto del test con fixture personalizzate. Questo restituirà un nuovo test, che sarà a sua volta estendibile, consentendo di comporre ulteriori fixture o di sovrascrivere quelle esistenti estendendolo secondo necessità. Per maggiori informazioni, consultare Estendi Contesto di 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
- Alias:
it.skip
Se si desidera saltare l'esecuzione di determinati test, ma non si vuole eliminare il codice per qualsiasi motivo, è possibile utilizzare test.skip per evitarne l'esecuzione.
import { assert, test } from 'vitest';
test.skip('skipped test', () => {
// Test saltato, nessun errore.
assert.equal(Math.sqrt(4), 3);
});È anche possibile saltare un test chiamando skip sul suo contesto dinamicamente:
import { assert, test } from 'vitest';
test('skipped test', context => {
context.skip();
// Test saltato, nessun errore.
assert.equal(Math.sqrt(4), 3);
});A partire da Vitest 3.1, se la condizione è sconosciuta, è possibile fornirla al metodo skip come primo argomento:
import { assert, test } from 'vitest';
test('skipped test', context => {
context.skip(Math.random() < 0.5, 'optional message');
// Test saltato, nessun errore.
assert.equal(Math.sqrt(4), 3);
});test.skipIf
- Alias:
it.skipIf
In alcuni casi, si potrebbero eseguire i test più volte con ambienti diversi, e alcuni di essi potrebbero essere specifici dell'ambiente. Invece di racchiudere il codice del test con un if, è possibile utilizzare test.skipIf per saltare il test ogni volta che la condizione specificata è vera.
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.skipIf(isDev)('prod only test', () => {
// Questo test viene eseguito solo in produzione.
});WARNING
Non puoi usare questa sintassi quando usi Vitest come controllore di tipi.
test.runIf
- Alias:
it.runIf
Opposto di test.skipIf.
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.runIf(isDev)('dev only test', () => {
// Questo test viene eseguito solo in sviluppo.
});WARNING
Non puoi usare questa sintassi quando usi Vitest come controllore di tipi.
test.only
- Alias:
it.only
Utilizzare test.only per eseguire solo determinati test all'interno di una data suite. Questo è utile durante il debug.
Opzionalmente, è possibile fornire un timeout (in millisecondi) per specificare il tempo massimo di attesa prima della terminazione. Il valore predefinito è 5 secondi e può essere configurato globalmente con testTimeout.
import { assert, test } from 'vitest';
test.only('test', () => {
// Solo questo test (e altri marcati con `only`) vengono eseguiti.
assert.equal(Math.sqrt(4), 2);
});A volte è molto utile eseguire solo i test marcati con only in un determinato file, ignorando tutti gli altri test dell'intera suite, che potrebbero inquinare l'output.
Per fare ciò, esegui vitest con il file specifico contenente i test in questione:
# vitest interesting.test.tstest.concurrent
- Alias:
it.concurrent
test.concurrent marca i test consecutivi per essere eseguiti in parallelo. Accetta il nome del test, una funzione asincrona con i test da raccogliere e un timeout opzionale (in millisecondi).
import { describe, test } from 'vitest';
// I due test marcati con `concurrent` verranno eseguiti in parallelo.
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 funzionano con i test concorrenti. Tutte le seguenti combinazioni sono valide:
test.concurrent(/* ... */);
test.skip.concurrent(/* ... */); // o test.concurrent.skip(/* ... */)
test.only.concurrent(/* ... */); // o test.concurrent.only(/* ... */)
test.todo.concurrent(/* ... */); // o test.concurrent.todo(/* ... */)Quando si eseguono test concorrenti, gli Snapshot e le Asserzioni devono utilizzare expect dal Contesto di Test locale per garantire che il test corretto venga rilevato.
test.concurrent('test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test.concurrent('test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});WARNING
Non puoi usare questa sintassi quando usi Vitest come controllore di tipi.
test.sequential
- Alias:
it.sequential
test.sequential marca un test come sequenziale. Questo è utile se si desidera eseguire i test in sequenza all'interno di describe.concurrent o con l'opzione da riga di comando --sequence.concurrent.
import { describe, test } from 'vitest';
// con l'opzione di configurazione { 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 () => {
/* ... */
});
// all'interno di una suite 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
Utilizzare test.todo per creare test stub da implementare in seguito. Nel report verrà mostrata una voce per questi test, in modo da sapere quanti test devono ancora essere implementati.
// Nel report verrà mostrata una voce per questo test.
test.todo('unimplemented test');test.fails
- Alias:
it.fails
Utilizzare test.fails per indicare esplicitamente che un'asserzione fallirà.
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
Non puoi usare questa sintassi quando usi Vitest come controllore di tipi.
test.each
- Alias:
it.each
TIP
Mentre test.each è fornito per la compatibilità con Jest, Vitest dispone anche di test.for con una funzionalità aggiuntiva per integrare TestContext.
Usa test.each quando devi eseguire lo stesso test con variabili diverse. È possibile iniettare parametri con la formattazione printf nel nome del test, seguendo l'ordine dei parametri della funzione di test.
%s: stringa%d: numero%i: intero%f: valore in virgola mobile%j: json%o: oggetto%#: indice basato su 0 del caso di test%$: indice basato su 1 del caso di test%%: singolo segno di percentuale ('%')
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);
});
// questo restituirà:
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3È anche possibile accedere alle proprietà degli oggetti e agli elementi degli array con il prefisso $:
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);
});
// questo restituirà:
// ✓ 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);
});
// questo restituirà:
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3È anche possibile accedere agli attributi degli oggetti con ., se si utilizzano oggetti come argomenti:
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);
});
// questo restituirà:
// ✓ add(1, b) -> 1b
// ✓ add(2, b) -> 2b
// ✓ add(3, b) -> 3bA partire da Vitest 0.25.3, puoi anche usare la tabella di stringhe template.
- La prima riga dovrebbe contenere i nomi delle colonne, separati da
|; - Una o più righe successive di dati fornite come espressioni letterali template utilizzando la sintassi
${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 elabora i $values con il metodo format di Chai. Se il valore è troppo troncato, puoi aumentare chaiConfig.truncateThreshold nel tuo file di configurazione.
WARNING
Non puoi usare questa sintassi quando usi Vitest come controllore di tipi.
test.for
- Alias:
it.for
Alternativa a test.each per fornire TestContext.
La differenza rispetto a test.each risiede nel modo in cui gli array vengono forniti negli argomenti. Gli argomenti non-array di test.for (incluso l'uso di stringhe template) funzionano esattamente come per test.each.
// `each` espande gli 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` non espande gli array (si notino le parentesi quadre attorno agli argomenti)
test.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => {
expect(a + b).toBe(expected);
});Il secondo argomento è TestContext e può essere utilizzato per snapshot concorrenti, ad esempio:
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 definisce un benchmark. In termini di Vitest, un benchmark è una funzione che definisce una serie di operazioni. Vitest esegue questa funzione più volte per visualizzare diversi risultati di performance.
Vitest utilizza la libreria tinybench "sotto il cofano", ereditando tutte le sue opzioni che possono essere utilizzate come terzo argomento.
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 massimo (in millisecondi) per l'esecuzione di un'attività di benchmark.
* @default 500
*/
time?: number;
/**
* Numero minimo di volte che un'attività dovrebbe essere eseguita, anche se l'opzione `time` è terminata.
* @default 10
*/
iterations?: number;
/**
* Funzione per ottenere il timestamp corrente in millisecondi.
*/
now?: () => number;
/**
* Un `AbortSignal` per abortire il benchmark.
*/
signal?: AbortSignal;
/**
* Lancia un errore se un'attività fallisce (gli eventi non funzioneranno se `true`).
*/
throws?: boolean;
/**
* Tempo di riscaldamento (in millisecondi).
* @default 100ms
*/
warmupTime?: number;
/**
* Iterazioni di riscaldamento.
* @default 5
*/
warmupIterations?: number;
/**
* Funzione di setup da eseguire prima di ogni attività di benchmark (ciclo).
*/
setup?: Hook;
/**
* Funzione di teardown da eseguire dopo ogni attività di benchmark (ciclo).
*/
teardown?: Hook;
}Dopo l'esecuzione del caso di test, le informazioni sulla struttura dell'output sono le seguenti:
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 {
/*
* L'ultimo errore che è stato lanciato durante l'esecuzione dell'attività.
*/
error?: unknown;
/**
* Il tempo totale (in millisecondi) impiegato per eseguire l'attività di benchmark (ciclo).
*/
totalTime: number;
/**
* Il valore minimo nei campioni.
*/
min: number;
/**
* Il valore massimo nei campioni.
*/
max: number;
/**
* Il numero di operazioni al secondo (Hertz).
*/
hz: number;
/**
* Quanto tempo impiega ogni operazione (in millisecondi).
*/
period: number;
/**
* Campioni di tempo di ogni iterazione dell'attività (in millisecondi).
*/
samples: number[];
/**
* Media dei campioni (stima della media della popolazione).
*/
mean: number;
/**
* Varianza dei campioni (stima della varianza della popolazione).
*/
variance: number;
/**
* Deviazione standard dei campioni (stima della deviazione standard della popolazione).
*/
sd: number;
/**
* Errore standard della media (ovvero la deviazione standard della distribuzione campionaria della media campionaria).
*/
sem: number;
/**
* Gradi di libertà.
*/
df: number;
/**
* Valore critico dei campioni.
*/
critical: number;
/**
* Margine di errore.
*/
moe: number;
/**
* Margine di errore relativo.
*/
rme: number;
/**
* Deviazione assoluta mediana.
*/
mad: number;
/**
* Percentile p50/mediana.
*/
p50: number;
/**
* Percentile p75.
*/
p75: number;
/**
* Percentile p99.
*/
p99: number;
/**
* Percentile p995.
*/
p995: number;
/**
* Percentile p999.
*/
p999: number;
}bench.skip
- Tipo:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
È possibile utilizzare la sintassi bench.skip per saltare l'esecuzione di determinati benchmark.
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
Utilizzare bench.only per eseguire solo determinati benchmark all'interno di una data suite. Questo è utile durante il debug.
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
Utilizzare bench.todo per creare benchmark stub da implementare in seguito.
import { bench } from 'vitest';
bench.todo('unimplemented test');Descrivi
Quando si utilizzano test o bench al livello superiore di un file, questi vengono raccolti come parte della suite implicita. Utilizzando describe, è possibile definire una nuova suite nel contesto corrente, come un insieme di test o benchmark correlati e altre suite annidate. Una suite consente di organizzare i test e i benchmark in modo che i report siano più chiari.
// basic.spec.ts
// organizzazione dei test.
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
// organizzazione dei benchmark.
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;
});
});
});È anche possibile annidare blocchi describe se si dispone di una gerarchia di test o benchmark:
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
Utilizzare describe.skip in una suite per evitare di eseguire un particolare blocco describe.
import { assert, describe, test } from 'vitest';
describe.skip('skipped suite', () => {
test('sqrt', () => {
// Suite saltata, nessun errore.
assert.equal(Math.sqrt(4), 3);
});
});describe.skipIf
- Alias:
suite.skipIf
In alcuni casi, si potrebbero eseguire le suite più volte con ambienti diversi, e alcune di esse potrebbero essere specifiche dell'ambiente. Invece di racchiudere la suite con un if, è possibile utilizzare describe.skipIf per saltare la suite ogni volta che la condizione specificata è vera.
import { describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.skipIf(isDev)('prod only test suite', () => {
// Questa suite di test viene eseguita solo in produzione.
});WARNING
Non puoi usare questa sintassi quando usi Vitest come controllore di tipi.
describe.runIf
- Alias:
suite.runIf
Opposto di describe.skipIf.
import { assert, describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.runIf(isDev)('dev only test suite', () => {
// Questa suite di test viene eseguita solo in sviluppo.
});WARNING
Non puoi usare questa sintassi quando usi Vitest come controllore di tipi.
describe.only
- Tipo:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
Utilizzare describe.only per eseguire solo determinate suite.
import { assert, describe, test } from 'vitest';
// Solo questa suite (e altre marcate con `only`) vengono eseguite.
describe.only('suite', () => {
test('sqrt', () => {
assert.equal(Math.sqrt(4), 3);
});
});
describe('other suite', () => {
// ... verrà saltata.
});A volte è molto utile eseguire test only in un certo file, ignorando tutti gli altri test dell'intera suite di test, che inquinano l'output.
Per fare ciò, esegui vitest con il file specifico contenente i test in questione:
# vitest interesting.test.tsdescribe.concurrent
- Alias:
suite.concurrent
describe.concurrent esegue tutte le suite e i test interni in parallelo.
import { describe, test } from 'vitest';
// Tutte le suite e i test all'interno di questa suite verranno eseguiti in parallelo.
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 funzionano con le suite concorrenti. Tutte le seguenti combinazioni sono valide:
describe.concurrent(/* ... */);
describe.skip.concurrent(/* ... */); // o describe.concurrent.skip(/* ... */)
describe.only.concurrent(/* ... */); // o describe.concurrent.only(/* ... */)
describe.todo.concurrent(/* ... */); // o describe.concurrent.todo(/* ... */)Quando si eseguono test concorrenti, gli Snapshot e le Asserzioni devono utilizzare expect dal Contesto di Test locale per garantire che il test corretto venga rilevato.
describe.concurrent('suite', () => {
test('concurrent test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test('concurrent test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
});WARNING
Non puoi usare questa sintassi quando usi Vitest come controllore di tipi.
describe.sequential
- Alias:
suite.sequential
describe.sequential in una suite marca ogni test come sequenziale. Questo è utile se si desidera eseguire i test in sequenza all'interno di describe.concurrent o con l'opzione da riga di 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
- Alias:
suite.shuffle
Vitest offre un modo per eseguire tutti i test in ordine casuale tramite il flag CLI --sequence.shuffle o l'opzione di configurazione sequence.shuffle. Tuttavia, se si desidera che solo una parte della suite di test esegua i test in ordine casuale, è possibile marcarla con questo flag.
import { describe, test } from 'vitest';
// o `describe('suite', { shuffle: true }, ...)`
describe.shuffle('suite', () => {
test('random test 1', async () => {
/* ... */
});
test('random test 2', async () => {
/* ... */
});
test('random test 3', async () => {
/* ... */
});
// `shuffle` è ereditato
describe('still random', () => {
test('random 4.1', async () => {
/* ... */
});
test('random 4.2', async () => {
/* ... */
});
});
// disabilita lo `shuffle` all'interno
describe('not random', { shuffle: false }, () => {
test('in order 5.1', async () => {
/* ... */
});
test('in order 5.2', async () => {
/* ... */
});
});
});
// l'ordine dipende dall'opzione `sequence.seed` nella configurazione (`Date.now()` per impostazione predefinita)..skip, .only e .todo funzionano con le suite casuali.
WARNING
Non puoi usare questa sintassi quando usi Vitest come controllore di tipi.
describe.todo
- Alias:
suite.todo
Utilizzare describe.todo per creare suite stub da implementare in seguito. Nel report verrà mostrata una voce per queste suite, in modo da sapere quante suite devono ancora essere implementate.
// Nel report verrà mostrata una voce per questa suite.
describe.todo('unimplemented suite');describe.each
- Alias:
suite.each
TIP
Mentre describe.each è fornito per la compatibilità con Jest, Vitest dispone anche di describe.for, che semplifica i tipi di argomento e si allinea con test.for.
Utilizzare describe.each se si dispone di più di un test che dipende dagli stessi dati.
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 partire da Vitest 0.25.3, puoi anche usare la tabella di stringhe template.
- La prima riga dovrebbe contenere i nomi delle colonne, separati da
|; - Una o più righe successive di dati fornite come espressioni letterali template utilizzando la sintassi
${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
Non puoi usare questa sintassi quando usi Vitest come controllore di tipi.
describe.for
- Alias:
suite.for
La differenza rispetto a describe.each risiede nel modo in cui il caso array viene fornito negli argomenti. Gli altri casi non-array (incluso l'uso di stringhe template) funzionano esattamente allo stesso modo.
// `each` espande il caso 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` non espande il caso 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);
});
});Setup e Teardown
Queste funzioni consentono di agganciarsi al ciclo di vita dei test per evitare la ripetizione del codice di setup e teardown. Si applicano al contesto corrente: il file, se utilizzate al livello superiore, o la suite corrente, se si trovano all'interno di un blocco describe. Questi hook non vengono chiamati quando si esegue Vitest come controllore di tipi.
beforeEach
- Tipo:
beforeEach(fn: () => Awaitable<void>, timeout?: number)
Registra una callback da chiamare prima dell'esecuzione di ciascun test nel contesto corrente. Se la funzione restituisce una promise, Vitest attende che la promise si risolva prima di eseguire il test.
Opzionalmente, è possibile passare un timeout (in millisecondi) che definisce il tempo massimo di attesa prima della terminazione. Il valore predefinito è 5 secondi.
import { beforeEach } from 'vitest';
beforeEach(async () => {
// Cancella i mock e aggiungi alcuni dati di test prima di ogni esecuzione del test.
await stopMocking();
await addUser({ name: 'John' });
});Qui, beforeEach assicura che l'utente venga aggiunto per ogni test.
beforeEach accetta anche una funzione di pulizia opzionale (equivalente a afterEach).
import { beforeEach } from 'vitest';
beforeEach(async () => {
// Chiamato una volta prima di ogni esecuzione del test.
await prepareSomething();
// Funzione di pulizia, chiamata una volta dopo ogni esecuzione del test.
return async () => {
await resetSomething();
};
});afterEach
- Tipo:
afterEach(fn: () => Awaitable<void>, timeout?: number)
Registra una callback da chiamare dopo che ciascuno dei test nel contesto corrente è stato completato. Se la funzione restituisce una promise, Vitest attende che la promise si risolva prima di continuare.
Opzionalmente, è possibile fornire un timeout (in millisecondi) per specificare il tempo massimo di attesa prima della terminazione. Il valore predefinito è 5 secondi.
import { afterEach } from 'vitest';
afterEach(async () => {
await clearTestingData(); // Cancella i dati di test dopo ogni esecuzione del test.
});Qui, afterEach assicura che i dati di test vengano cancellati dopo ogni esecuzione del test.
TIP
Vitest 1.3.0 ha aggiunto l'hook onTestFinished. È possibile chiamarlo durante l'esecuzione del test per pulire qualsiasi stato dopo che il test è terminato.
beforeAll
- Tipo:
beforeAll(fn: () => Awaitable<void>, timeout?: number)
Registra una callback da chiamare una volta prima di iniziare l'esecuzione di tutti i test nel contesto corrente. Se la funzione restituisce una promise, Vitest attende che la promise si risolva prima di eseguire i test.
Opzionalmente, è possibile fornire un timeout (in millisecondi) per specificare il tempo massimo di attesa prima della terminazione. Il valore predefinito è 5 secondi.
import { beforeAll } from 'vitest';
beforeAll(async () => {
await startMocking(); // Chiamato una volta prima di tutti i test.
});Qui beforeAll assicura che i dati mock siano impostati prima dell'esecuzione dei test.
beforeAll accetta anche una funzione di pulizia opzionale (equivalente a afterAll).
import { beforeAll } from 'vitest';
beforeAll(async () => {
// Chiamato una volta prima di tutti i test.
await startMocking();
// Funzione di pulizia, chiamata una volta dopo tutti i test.
return async () => {
await stopMocking();
};
});afterAll
- Tipo:
afterAll(fn: () => Awaitable<void>, timeout?: number)
Registra una callback da chiamare una volta dopo che tutti i test sono stati eseguiti nel contesto corrente. Se la funzione restituisce una promise, Vitest attende che la promise si risolva prima di continuare.
Opzionalmente, è possibile fornire un timeout (in millisecondi) per specificare il tempo massimo di attesa prima della terminazione. Il valore predefinito è 5 secondi.
import { afterAll } from 'vitest';
afterAll(async () => {
await stopMocking(); // Questo metodo viene chiamato dopo l'esecuzione di tutti i test.
});Qui afterAll assicura che il metodo stopMocking venga chiamato dopo l'esecuzione di tutti i test.
Hook di Test
Vitest fornisce alcuni hook che è possibile chiamare durante l'esecuzione del test per pulire lo stato una volta che il test è terminato.
WARNING
Questi hook lanceranno un errore se vengono chiamati al di fuori del corpo del test.
onTestFinished
Questo hook viene sempre chiamato dopo che il test è terminato. Viene chiamato dopo gli hook afterEach, poiché possono influenzare il risultato del test. Riceve un oggetto ExtendedContext come 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 si stanno eseguendo test in parallelo, si dovrebbe sempre utilizzare l'hook onTestFinished dal contesto del test, poiché Vitest non tiene traccia dei test concorrenti negli hook globali:
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFinished }) => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});Questo hook è particolarmente utile quando si crea una logica riutilizzabile:
// Questo può essere in un file separato.
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
Questo hook viene sempre chiamato in ordine inverso e non è influenzato dall'opzione sequence.hooks.
onTestFailed
Questo hook viene chiamato solo dopo che il test è fallito. Viene chiamato dopo gli hook afterEach, poiché possono influenzare il risultato del test. Riceve un oggetto ExtendedContext come beforeEach e afterEach. Questo hook è utile per il debug.
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 si stanno eseguendo test in parallelo, si dovrebbe sempre utilizzare l'hook onTestFailed dal contesto del test, poiché Vitest non tiene traccia dei test concorrenti negli hook globali:
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');
});