Contesto del Test
Ispirandosi alle Playwright Fixtures, il contesto di test di Vitest permette di definire utilità, stati e fixture utilizzabili all'interno dei test.
Utilizzo
Il primo argomento di ogni callback della funzione di test è un contesto di test.
import { it } from 'vitest';
it('should work', ctx => {
// stampa il nome del test
console.log(ctx.task.name);
});
Contesto del Test Integrato
context.task
Un oggetto di sola lettura contenente metadati relativi al test.
context.expect
L'API expect
associata al test corrente:
import { it } from 'vitest';
it('math is easy', ({ expect }) => {
expect(2 + 2).toBe(4);
});
Questa API è utile per eseguire test snapshot in parallelo, poiché l'aspettativa globale non è in grado di tracciarli correttamente:
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
Salta l'esecuzione dei test successivi e contrassegna il test come saltato:
import { expect, it } from 'vitest';
it('math is hard', ({ skip }) => {
skip();
expect(2 + 2).toBe(5);
});
Estendere il Contesto del Test
Vitest offre due modi distinti per estendere il contesto di test.
test.extend
WARNING
Questa API è disponibile a partire da Vitest 0.32.3.
Come Playwright, puoi usare questo metodo per definire la tua API test
con fixture personalizzate e riutilizzarle ovunque.
Per esempio, creiamo prima myTest
con due fixture, todos
e archive
.
// my-test.ts
import { test } from 'vitest';
const todos = [];
const archive = [];
export const myTest = test.extend({
todos: async ({ task }, use) => {
// imposta la fixture prima di ogni funzione di test
todos.push(1, 2, 3);
// usa il valore della fixture
await use(todos);
// pulisci la fixture dopo ogni funzione di test
todos.length = 0;
},
archive,
});
Quindi possiamo importarlo e utilizzarlo.
import { expect } from 'vitest';
import { myTest } from './my-test.ts';
myTest('add items to todos', ({ todos }) => {
expect(todos.length).toBe(3);
todos.add(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);
});
Possiamo anche aggiungere ulteriori fixture o sovrascrivere fixture esistenti estendendo myTest
.
export const myTest2 = myTest.extend({
settings: {
// ...
},
});
Inizializzazione delle Fixture
Il runner di Vitest inizializzerà le fixture in modo intelligente e le inserirà nel contesto di test in base all'utilizzo.
import { test } from 'vitest';
async function todosFn({ task }, use) {
await use([1, 2, 3]);
}
const myTest = test.extend({
todos: todosFn,
archive: [],
});
// todosFn non verrà eseguito
myTest('', () => {});
myTest('', ({ archive }) => {});
// todosFn verrà eseguito
myTest('', ({ todos }) => {});
WARNING
Quando si utilizza test.extend()
con le fixture, è consigliabile utilizzare sempre il pattern di destrutturazione degli oggetti { todos }
per accedere al contesto sia nella funzione fixture sia nella funzione test.
TypeScript
Per specificare i tipi per le fixture per tutti i contesti personalizzati, è possibile passare il tipo di fixture come parametro generico.
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
I contesti sono diversi per ogni test e possono essere acceduti ed estesi all'interno degli hook beforeEach
e afterEach
.
import { beforeEach, it } from 'vitest';
beforeEach(async context => {
// estendi il contesto
context.foo = 'bar';
});
it('should work', ({ foo }) => {
console.log(foo); // 'bar'
});
TypeScript
Per specificare i tipi delle proprietà per tutti i contesti personalizzati, è possibile estendere il tipo TestContext
aggiungendo
declare module 'vitest' {
export interface TestContext {
foo?: string;
}
}
Se si desidera specificare i tipi di proprietà solo per hook specifici beforeEach
, afterEach
, it
e test
, è possibile passare il tipo come parametro generico.
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'
});