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.push(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.
Automatyczne fixture
WARNING
Ta funkcja jest dostępna od wersji Vitest 1.3.0.
Vitest obsługuje również składnię krotek dla fixtures, umożliwiając przekazywanie opcji dla każdego fixture. Na przykład możesz go użyć do jawnego zainicjowania fixture, nawet jeśli nie jest on używany w testach.
import { test as base } from 'vitest';
const test = base.extend({
fixture: [
async ({}, use) => {
// ta funkcja zostanie wykonana
setup();
await use();
teardown();
},
{ auto: true }, // Oznacz jako automatyczny fixture
],
});
test('', () => {});
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'
});