Kontekst Testowy
Kontekst testowy Vitest, wzorowany na Playwright Fixtures, umożliwia definiowanie narzędzi, stanów i fixtures, które mogą być używane w testach.
Użycie
Kontekst testowy jest przekazywany jako pierwszy argument do funkcji callback każdego testu.
import { it } from 'vitest';
it('powinno działać', ctx => {
// wyświetla nazwę testu
console.log(ctx.task.name);
});
Wbudowany Kontekst Testowy
context.task
Obiekt tylko do odczytu zawierający metadane dotyczące testu.
context.expect
API expect
powiązane z aktualnie wykonywanym testem:
import { it } from 'vitest';
it('matematyka jest prosta', ({ expect }) => {
expect(2 + 2).toBe(4);
});
To API jest przydatne podczas współbieżnego uruchamiania testów migawkowych, ponieważ globalny expect
nie jest w stanie ich śledzić:
import { it } from 'vitest';
it.concurrent('matematyka jest prosta', ({ expect }) => {
expect(2 + 2).toMatchInlineSnapshot();
});
it.concurrent('matematyka jest trudna', ({ expect }) => {
expect(2 * 2).toMatchInlineSnapshot();
});
context.skip
Pomija dalsze wykonywanie testu i oznacza go jako pominięty:
import { expect, it } from 'vitest';
it('matematyka jest trudna', ({ skip }) => {
skip();
expect(2 + 2).toBe(5);
});
Rozszerzanie Kontekstu Testowego
Vitest oferuje dwa sposoby rozszerzania kontekstu testowego.
test.extend
WARNING
To API jest dostępne od Vitest 0.32.3.
Podobnie jak w Playwright, możesz użyć tej metody, aby zdefiniować własne API test
z niestandardowymi fixtures i używać go w dowolnym miejscu.
Przykładowo, tworzymy myTest
z dwoma fixtures: todos
i archive
.
// my-test.ts
import { test } from 'vitest';
const todos = [];
const archive = [];
export const myTest = test.extend({
todos: async ({ task }, use) => {
// ustawienie fixture przed każdą funkcją testową
todos.push(1, 2, 3);
// użycie wartości fixture
await use(todos);
// wyczyszczenie fixture po każdej funkcji testowej
todos.length = 0;
},
archive,
});
Następnie możemy go zaimportować i użyć.
import { expect } from 'vitest';
import { myTest } from './my-test.ts';
myTest('dodaj elementy do todos', ({ todos }) => {
expect(todos.length).toBe(3);
todos.add(4);
expect(todos.length).toBe(4);
});
myTest('przenieś elementy z todos do 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);
});
Możemy również dodać więcej fixtures lub zastąpić istniejące, rozszerzając myTest
.
export const myTest2 = myTest.extend({
settings: {
// ...
},
});
Inicjalizacja Fixture
Vitest inteligentnie inicjalizuje fixtures i wstrzykuje je do kontekstu testowego w zależności od ich użycia.
import { test } from 'vitest';
async function todosFn({ task }, use) {
await use([1, 2, 3]);
}
const myTest = test.extend({
todos: todosFn,
archive: [],
});
// todosFn nie zostanie wykonane
myTest('', () => {});
myTest('', ({ archive }) => {});
// todosFn zostanie uruchomione
myTest('', ({ todos }) => {});
WARNING
Używając test.extend()
z fixtures, zawsze powinieneś używać destrukturyzacji obiektu { todos }
, aby uzyskać dostęp do kontekstu zarówno w funkcji fixture, jak i w funkcji testowej.
TypeScript
Aby określić typy fixture dla niestandardowych kontekstów, możesz przekazać typ fixtures jako argument generyczny.
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
i afterEach
Konteksty są różne dla każdego testu. Możesz uzyskać do nich dostęp i rozszerzyć je w hookach beforeEach
i afterEach
.
import { beforeEach, it } from 'vitest';
beforeEach(async context => {
// rozszerzenie kontekstu
context.foo = 'bar';
});
it('powinno działać', ({ foo }) => {
console.log(foo); // 'bar'
});
TypeScript
Aby zdefiniować typy właściwości dla wszystkich niestandardowych kontekstów, możesz rozszerzyć typ TestContext
przez dodanie:
declare module 'vitest' {
export interface TestContext {
foo?: string;
}
}
Jeśli chcesz określić typy właściwości tylko dla wybranych hooków beforeEach
, afterEach
, it
i test
, możesz przekazać typ jako argument generyczny.
interface LocalTestContext {
foo: string;
}
beforeEach<LocalTestContext>(async context => {
// typeof context is 'TestContext & LocalTestContext'
context.foo = 'bar';
});
it<LocalTestContext>('powinno działać', ({ foo }) => {
// typeof foo is 'string'
console.log(foo); // 'bar'
});