Dokumentacja API Testów
Poniższe typy są używane w sygnaturach typów poniżej:
type Awaitable<T> = T | PromiseLike<T>;
type TestFunction = () => Awaitable<void>;
interface TestOptions {
/**
* Powoduje niepowodzenie testu, jeśli jego wykonanie zajmie zbyt dużo czasu.
*/
timeout?: number;
/**
* Ponawia test określoną liczbę razy, jeśli zakończy się niepowodzeniem.
*
* @default 0
*/
retry?: number;
/**
* Powtarza ten sam test kilka razy, nawet jeśli za każdym razem zakończy się niepowodzeniem.
* Jeśli używasz opcji "retry" (ponów) i test zakończy się niepowodzeniem, każde ponowienie zostanie użyte w każdym cyklu.
* Przydatne do debugowania losowych awarii.
*
* @default 0
*/
repeats?: number;
}Gdy funkcja testowa zwraca obietnicę, uruchamiacz poczeka na jej rozwiązanie, aby zebrać asynchroniczne asercje. Jeśli obietnica zostanie odrzucona, test zakończy się niepowodzeniem.
TIP
W Jest, TestFunction może być również typu (done: DoneCallback) => void. Jeśli ta forma jest używana, test nie zostanie zakończony, dopóki done nie zostanie wywołane. Możesz osiągnąć to samo za pomocą funkcji async, zobacz sekcję Przewodnik migracji - Callback Done.
Większość opcji obsługuje zarówno składnię kropkową, jak i składnię obiektową, co pozwala na użycie preferowanego stylu.
import { test } from 'vitest';
test.skip('skipped test', () => {
// some logic that fails right now
});import { test } from 'vitest';
test('skipped test', { skip: true }, () => {
// some logic that fails right now
});test
- Alias:
it
test definiuje zestaw powiązanych oczekiwań. Przyjmuje nazwę testu i funkcję, która zawiera oczekiwania do przetestowania.
Opcjonalnie, możesz podać limit czasu (w milisekundach) określający, jak długo czekać przed zakończeniem testu. Domyślnie jest to 5 sekund i można to skonfigurować globalnie za pomocą testTimeout.
import { expect, test } from 'vitest';
test('powinien działać zgodnie z oczekiwaniami', () => {
expect(Math.sqrt(4)).toBe(2);
});test.extend
- Alias:
it.extend
Użyj test.extend, aby rozszerzyć kontekst testowy o niestandardowe "fixtures". Zwróci to nowy test, który również można rozszerzać, dzięki czemu możesz komponować więcej "fixtures" lub nadpisywać istniejące, rozszerzając go zgodnie z potrzebami. Zobacz Rozszerzanie Kontekstu Testowego aby uzyskać więcej informacji.
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('dodaje element', ({ todos }) => {
expect(todos.length).toBe(3);
todos.push(4);
expect(todos.length).toBe(4);
});test.skip
- Alias:
it.skip
Jeśli chcesz pominąć uruchamianie niektórych testów, ale nie chcesz usuwać kodu, możesz użyć test.skip, aby uniknąć ich uruchamiania.
import { assert, test } from 'vitest';
test.skip('pominięty test', () => {
// Test pominięty, brak błędu
assert.equal(Math.sqrt(4), 3);
});Możesz również pominąć test, wywołując skip na jego kontekście dynamicznie:
import { assert, test } from 'vitest';
test('pominięty test', context => {
context.skip();
// Test pominięty, brak błędu
assert.equal(Math.sqrt(4), 3);
});test.skipIf
- Alias:
it.skipIf
W niektórych przypadkach możesz uruchamiać testy wielokrotnie z różnymi środowiskami, a niektóre z testów mogą być specyficzne dla danego środowiska. Zamiast opakowywać kod testowy za pomocą if, możesz użyć test.skipIf, aby pominąć test, gdy warunek jest spełniony (prawdziwy).
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.skipIf(isDev)('test tylko dla produkcji', () => {
// ten test uruchamia się tylko w środowisku produkcyjnym
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako sprawdzania typów.
test.runIf
- Alias:
it.runIf
Odwrotność test.skipIf.
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.runIf(isDev)('test tylko dla deweloperów', () => {
// ten test uruchamia się tylko w środowisku deweloperskim
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako sprawdzania typów.
test.only
- Alias:
it.only
Użyj test.only, aby uruchamiać tylko określone testy w danym zestawie. Jest to przydatne podczas debugowania.
Opcjonalnie, możesz podać limit czasu (w milisekundach) określający, jak długo czekać przed zakończeniem testu. Domyślnie jest to 5 sekund i można to skonfigurować globalnie za pomocą testTimeout.
import { assert, test } from 'vitest';
test.only('test', () => {
// Tylko ten test (i inne oznaczone jako only) są uruchamiane
assert.equal(Math.sqrt(4), 2);
});Czasami bardzo przydatne jest uruchamianie testów only w określonym pliku, ignorując wszystkie inne testy z całego zestawu testów, które zakłócają wynik.
Aby to zrobić, uruchom vitest z określonym plikiem zawierającym testy, o które chodzi.
# vitest interesujacy.test.tstest.concurrent
- Alias:
it.concurrent
test.concurrent oznacza kolejne testy do uruchomienia równolegle. Przyjmuje nazwę testu, funkcję asynchroniczną z testami do wykonania i opcjonalny limit czasu (w milisekundach).
import { describe, test } from 'vitest';
// Dwa testy oznaczone jako concurrent zostaną uruchomione równolegle
describe('suite', () => {
test('test szeregowy', async () => {
/* ... */
});
test.concurrent('test współbieżny 1', async () => {
/* ... */
});
test.concurrent('test współbieżny 2', async () => {
/* ... */
});
});test.skip, test.only i test.todo działają z testami współbieżnymi. Wszystkie poniższe kombinacje są prawidłowe:
test.concurrent(/* ... */);
test.skip.concurrent(/* ... */); // lub test.concurrent.skip(/* ... */)
test.only.concurrent(/* ... */); // lub test.concurrent.only(/* ... */)
test.todo.concurrent(/* ... */); // lub test.concurrent.todo(/* ... */)Podczas uruchamiania testów współbieżnych, "Snapshots" i "Assertions" muszą używać expect z lokalnego Kontekstu Testowego, aby zapewnić wykrycie właściwego testu.
test.concurrent('test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test.concurrent('test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako sprawdzania typów.
test.sequential
- Alias:
it.sequential
test.sequential oznacza test jako sekwencyjny. Jest to przydatne, jeśli chcesz uruchamiać testy po kolei wewnątrz describe.concurrent lub z opcją wiersza poleceń --sequence.concurrent.
import { describe, test } from 'vitest';
// z opcją konfiguracyjną { 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 () => {
/* ... */
});
// wewnątrz równoległego zestawu testów
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
Użyj test.todo, aby utworzyć "stuby" testów do zaimplementowania w przyszłości. W raporcie zostanie wyświetlony wpis dla tych testów, dzięki czemu będziesz wiedział, ile testów musisz jeszcze zaimplementować.
// W raporcie zostanie wyświetlony wpis dla tego testu
test.todo('niezaimplementowany test');test.fails
- Alias:
it.fails
Użyj test.fails, aby wskazać, że asercja ma zakończyć się niepowodzeniem.
import { expect, test } from 'vitest';
function myAsyncFunc() {
return new Promise(resolve => resolve(1));
}
test.fails('test oczekiwanego niepowodzenia', async () => {
await expect(myAsyncFunc()).rejects.toBe(1);
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako sprawdzania typów.
test.each
- Alias:
it.each
TIP
Podczas gdy test.each jest dostarczony dla kompatybilności z Jest, Vitest posiada również test.for z dodatkową funkcją integracji TestContext.
Użyj test.each, gdy musisz uruchomić ten sam test z różnymi zestawami danych. Możesz wstrzykiwać parametry za pomocą formatowania printf w nazwie testu w kolejności parametrów funkcji testowej.
%s: string%d: number%i: integer%f: wartość zmiennoprzecinkowa%j: json%o: object%#: indeks przypadku testowego%%: pojedynczy znak procenta
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);
});
// to zwróci
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3Możesz również uzyskać dostęp do właściwości obiektu za pomocą prefiksu $, jeśli używasz obiektów jako argumentów:
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);
});
// to zwróci
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3Możesz również uzyskać dostęp do atrybutów obiektu za pomocą ., jeśli używasz obiektów jako argumentów:
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);
});
// to zwróci
// ✓ add(1, b) -> 1b
// ✓ add(2, b) -> 2b
// ✓ add(3, b) -> 3bPocząwszy od Vitest 0.25.3, możesz również użyć tabeli ciągów szablonowych (template string table).
- Pierwszy wiersz powinien zawierać nazwy kolumn, oddzielone znakiem
|; - Jeden lub więcej kolejnych wierszy danych dostarczonych jako wyrażenia literałów szablonowych (template literal expressions) przy użyciu składni
${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'}
`('zwraca $expected, gdy $a jest dodane do $b', ({ a, b, expected }) => {
expect(a + b).toBe(expected);
});TIP
Vitest przetwarza $values za pomocą metody format biblioteki Chai. Jeśli wartość jest zbyt obcięta, możesz zwiększyć chaiConfig.truncateThreshold w pliku konfiguracyjnym.
WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako sprawdzania typów.
test.for
- Alias:
it.for
Alternatywa dla test.each, która zapewnia TestContext.
Różnica w stosunku do test.each polega na tym, jak przypadek tablicowy jest przekazywany w argumentach. Pozostałe przypadki niebędące tablicami (w tym użycie szablonów stringowych) działają dokładnie tak samo.
// `each` rozpakowuje przypadek tablicowy
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// `for` nie rozpakowuje przypadku tablicowego
test.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => {
expect(a + b).toBe(expected);
});Drugi argument to TestContext, który może być użyty na przykład do asynchronicznego snapshotowania:
test.concurrent.for([
[1, 1],
[1, 2],
[2, 1],
])('add(%i, %i)', ([a, b], { expect }) => {
expect(a + b).matchSnapshot();
});bench
- Typ:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
bench definiuje "benchmark". W terminologii Vitest, "benchmark" to funkcja, która definiuje serię operacji. Vitest uruchamia tę funkcję wiele razy, aby przedstawić różne wyniki wydajności.
Vitest używa biblioteki tinybench wewnętrznie, dziedzicząc wszystkie jej opcje, które mogą być używane jako trzeci argument.
import { bench } from 'vitest';
bench(
'normalne sortowanie',
() => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
},
{ time: 1000 }
);export interface Options {
/**
* Czas potrzebny na uruchomienie zadania testu wydajnościowego (milisekundy).
* @default 500
*/
time?: number;
/**
* Liczba powtórzeń zadania, nawet jeśli opcja czasu została zakończona.
* @default 10
*/
iterations?: number;
/**
* Funkcja pobierania aktualnego znacznika czasu w milisekundach.
*/
now?: () => number;
/**
* AbortSignal do przerywania testu wydajnościowego.
*/
signal?: AbortSignal;
/**
* Zgłoś wyjątek, jeśli zadanie zakończy się niepowodzeniem (zdarzenia nie będą działać, jeśli true)
*/
throws?: boolean;
/**
* Czas przygotowania (milisekundy).
* @default 100ms
*/
warmupTime?: number;
/**
* Iteracje przygotowawcze.
* @default 5
*/
warmupIterations?: number;
/**
* Funkcja przygotowania do uruchomienia przed każdym zadaniem testu wydajnościowego (cykl).
*/
setup?: Hook;
/**
* Funkcja sprzątająca do uruchomienia po każdym zadaniu testu wydajnościowego (cykl).
*/
teardown?: Hook;
}Po uruchomieniu przypadku testowego, informacja o strukturze wyjściowej jest następująca:
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 {
/*
* ostatni błąd wyrzucony podczas uruchamiania zadania
*/
error?: unknown;
/**
* Czas w milisekundach potrzebny do uruchomienia zadania benchmarku (cyklu).
*/
totalTime: number;
/**
* wartość minimalna w próbkach
*/
min: number;
/**
* wartość maksymalna w próbkach
*/
max: number;
/**
* liczba operacji na sekundę
*/
hz: number;
/**
* ile czasu zajmuje każda operacja (ms)
*/
period: number;
/**
* próbki czasu iteracji każdego zadania (ms)
*/
samples: number[];
/**
* średnia próbek (szacunek średniej populacji)
*/
mean: number;
/**
* wariancja próbek (szacunek wariancji populacji)
*/
variance: number;
/**
* odchylenie standardowe próbek (szacunek odchylenia standardowego populacji)
*/
sd: number;
/**
* błąd standardowy średniej (czyli odchylenie standardowe rozkładu próbkowania średniej próbki)
*/
sem: number;
/**
* stopnie swobody
*/
df: number;
/**
* wartość krytyczna próbek
*/
critical: number;
/**
* margines błędu
*/
moe: number;
/**
* względny margines błędu
*/
rme: number;
/**
* mediana bezwzględnego odchylenia
*/
mad: number;
/**
* centyl p50/mediana
*/
p50: number;
/**
* centyl p75
*/
p75: number;
/**
* centyl p99
*/
p99: number;
/**
* centyl p995
*/
p995: number;
/**
* centyl p999
*/
p999: number;
}bench.skip
- Typ:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
Możesz użyć składni bench.skip, aby pominąć uruchamianie niektórych testów wydajnościowych.
import { bench } from 'vitest';
bench.skip('normalne sortowanie', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});bench.only
- Typ:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
Użyj bench.only, aby uruchamiać tylko określone testy wydajnościowe w danym zestawie. Jest to przydatne podczas debugowania.
import { bench } from 'vitest';
bench.only('normalne sortowanie', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});bench.todo
- Typ:
(name: string | Function) => void
Użyj bench.todo, aby utworzyć "stuby" testów wydajnościowych do zaimplementowania w przyszłości.
import { bench } from 'vitest';
bench.todo('niezaimplementowany test');describe
Kiedy używasz test lub bench na najwyższym poziomie pliku, są one traktowane jako część domyślnego zestawu testów (suite) w tym pliku. Używając describe, możesz zdefiniować nowy zestaw testów w bieżącym kontekście, jako grupę powiązanych testów, benchmarków i innych zagnieżdżonych zestawów. Zestawy testów pozwalają organizować testy i benchmarki, dzięki czemu raporty są bardziej czytelne.
// basic.spec.ts
// organizing tests
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
// organizing 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;
});
});
});Możesz również zagnieżdżać bloki describe, aby stworzyć hierarchię testów lub benchmarków:
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
Użyj describe.skip, aby pominąć wykonanie konkretnego bloku describe.
import { assert, describe, test } from 'vitest';
describe.skip('skipped suite', () => {
test('sqrt', () => {
// Suite skipped, no error
assert.equal(Math.sqrt(4), 3);
});
});describe.skipIf
- Alias:
suite.skipIf
W niektórych przypadkach możesz chcieć uruchamiać zestawy testów wielokrotnie, w różnych środowiskach. Niektóre z tych zestawów mogą być specyficzne dla konkretnego środowiska. Zamiast używać instrukcji if do warunkowego uruchamiania zestawu testów, możesz użyć describe.skipIf, aby pominąć zestaw, gdy dany warunek jest spełniony.
import { describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.skipIf(isDev)('prod only test', () => {
// this test only runs in production
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako sprawdzania typów.
describe.runIf
- Alias:
suite.runIf
Przeciwieństwo describe.skipIf.
import { assert, describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.runIf(isDev)('dev only test suite', () => {
// this test suite only runs in development
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako sprawdzania typów.
describe.only
- Typ:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
Użyj describe.only, aby uruchomić tylko określone zestawy testów.
import { assert, describe, test } from 'vitest';
// Only this suite (and others marked with only) are run
describe.only('suite', () => {
test('sqrt', () => {
assert.equal(Math.sqrt(4), 3);
});
});
describe('other suite', () => {
// ... will be skipped
});Czasami przydatne jest uruchomienie testów oznaczonych jako only w konkretnym pliku, ignorując pozostałe testy z całego projektu, które mogłyby zakłócić wynik.
Aby to zrobić, uruchom vitest z określonym plikiem zawierającym testy, o których mowa.
# vitest interesting.test.tsdescribe.concurrent
- Alias:
suite.concurrent
describe.concurrent uruchamia wszystkie wewnętrzne zestawy i testy równolegle
import { describe, test } from 'vitest';
// Wszystkie zestawy i testy w ramach tego zestawu będą uruchamiane równolegle
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 () => {
/* ... */
});
});Metody .skip, .only i .todo działają z zestawami współbieżnymi. Wszystkie poniższe kombinacje są poprawne:
describe.concurrent(/* ... */);
describe.skip.concurrent(/* ... */); // or describe.concurrent.skip(/* ... */)
describe.only.concurrent(/* ... */); // or describe.concurrent.only(/* ... */)
describe.todo.concurrent(/* ... */); // or describe.concurrent.todo(/* ... */)Uruchamiając testy współbieżne, upewnij się, że migawki (Snapshots) i asercje (Assertions) korzystają z expect z lokalnego Kontekstu Testowego. Zapewni to poprawne wykrywanie testów.
describe.concurrent('suite', () => {
test('concurrent test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test('concurrent test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako sprawdzania typów.
describe.sequential
- Alias:
suite.sequential
describe.sequential w zestawie testów oznacza każdy test jako sekwencyjny. Jest to przydatne, jeśli chcesz uruchamiać testy sekwencyjnie wewnątrz bloku describe.concurrent lub z opcją wiersza poleceń --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 umożliwia uruchomienie wszystkich testów w losowej kolejności za pomocą flagi CLI --sequence.shuffle lub opcji konfiguracyjnej sequence.shuffle. Jeśli chcesz, aby tylko część zestawu testów była uruchamiana w losowej kolejności, możesz oznaczyć tę część za pomocą describe.shuffle.
import { describe, test } from 'vitest';
describe.shuffle('suite', () => {
test('random test 1', async () => {
/* ... */
});
test('random test 2', async () => {
/* ... */
});
test('random test 3', async () => {
/* ... */
});
});
// order depends on sequence.seed option in config (Date.now() by default)Metody .skip, .only i .todo działają z losowymi zestawami testów.
WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako sprawdzania typów.
describe.todo
- Alias:
suite.todo
Użyj describe.todo, aby utworzyć szkielety (stuby) zestawów testów do zaimplementowania w przyszłości. W raporcie zostanie wyświetlony wpis dla tych testów, dzięki czemu będziesz wiedzieć, ile testów musisz jeszcze zaimplementować.
// An entry will be shown in the report for this suite
describe.todo('unimplemented suite');describe.each
- Alias:
suite.each
Użyj describe.each, jeśli masz więcej niż jeden test, który zależy od tych samych danych.
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);
});
});Począwszy od Vitest 0.25.3, możesz również użyć tabeli ciągów szablonowych (template string table).
- Pierwszy wiersz powinien zawierać nazwy kolumn, oddzielone znakiem
|; - Jeden lub więcej kolejnych wierszy danych dostarczonych jako wyrażenia literałów szablonowych przy użyciu składni
${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
Nie możesz używać tej składni, gdy używasz Vitest jako sprawdzania typów.
Konfiguracja i Demontaż (Setup and Teardown)
Te funkcje pozwalają na wykorzystanie cyklu życia testów, aby uniknąć powtarzania kodu konfiguracji i demontażu. Mają one zastosowanie do bieżącego kontekstu: pliku, jeśli są używane na najwyższym poziomie, lub bieżącego zestawu testów, jeśli znajdują się wewnątrz bloku describe. Te hooki nie są wywoływane, gdy uruchamiasz Vitest jako sprawdzanie typów.
beforeEach
- Typ:
beforeEach(fn: () => Awaitable<void>, timeout?: number)
Rejestruje funkcję zwrotną, która zostanie wywołana przed każdym testem w bieżącym kontekście. Jeśli funkcja zwraca obietnicę, Vitest czeka na jej rozwiązanie przed uruchomieniem testu.
Opcjonalnie możesz przekazać limit czasu (w milisekundach) określający, jak długo czekać przed zakończeniem. Domyślna wartość to 5 sekund.
import { beforeEach } from 'vitest';
beforeEach(async () => {
// Clear mocks and add some testing data after before each test run
await stopMocking();
await addUser({ name: 'John' });
});W tym przypadku beforeEach gwarantuje, że użytkownik zostanie dodany przed każdym testem.
beforeEach akceptuje również opcjonalną funkcję czyszczącą, działającą analogicznie do afterEach.
import { beforeEach } from 'vitest';
beforeEach(async () => {
// called once before each test run
await prepareSomething();
// clean up function, called once after each test run
return async () => {
await resetSomething();
};
});afterEach
- Typ:
afterEach(fn: () => Awaitable<void>, timeout?: number)
Rejestruje funkcję zwrotną, która zostanie wywołana po każdym teście w bieżącym kontekście. Jeśli funkcja zwraca obietnicę, Vitest czeka, aż obietnica zostanie rozwiązana przed kontynuowaniem.
Opcjonalnie możesz podać limit czasu (w milisekundach) określający, jak długo czekać przed zakończeniem. Domyślna wartość to 5 sekund.
import { afterEach } from 'vitest';
afterEach(async () => {
await clearTestingData(); // clear testing data after each test run
});W tym przypadku afterEach gwarantuje, że dane testowe zostaną wyczyszczone po każdym teście.
TIP
Vitest 1.3.0 dodał hook onTestFinished. Możesz go wywołać podczas wykonywania testu, aby wyczyścić dowolny stan po zakończeniu działania testu.
beforeAll
- Typ:
beforeAll(fn: () => Awaitable<void>, timeout?: number)
Rejestruje funkcję zwrotną, która zostanie wywołana raz, przed uruchomieniem wszystkich testów w bieżącym kontekście. Jeśli funkcja zwraca obietnicę, Vitest czeka na jej rozwiązanie przed uruchomieniem testów.
Opcjonalnie możesz podać limit czasu (w milisekundach) określający, jak długo czekać przed zakończeniem. Domyślna wartość to 5 sekund.
import { beforeAll } from 'vitest';
beforeAll(async () => {
await startMocking(); // called once before all tests run
});W tym przypadku beforeAll gwarantuje, że dane mockowe zostaną skonfigurowane przed uruchomieniem testów.
beforeAll akceptuje również opcjonalną funkcję czyszczącą, działającą analogicznie do afterAll.
import { beforeAll } from 'vitest';
beforeAll(async () => {
// called once before all tests run
await startMocking();
// clean up function, called once after all tests run
return async () => {
await stopMocking();
};
});afterAll
- Typ:
afterAll(fn: () => Awaitable<void>, timeout?: number)
Rejestruje funkcję zwrotną, która zostanie wywołana raz, po uruchomieniu wszystkich testów w bieżącym kontekście. Jeśli funkcja zwraca obietnicę, Vitest czeka, aż obietnica zostanie rozwiązana przed kontynuowaniem.
Opcjonalnie możesz podać limit czasu (w milisekundach) określający, jak długo czekać przed zakończeniem. Domyślna wartość to 5 sekund.
import { afterAll } from 'vitest';
afterAll(async () => {
await stopMocking(); // this method is called after all tests run
});W tym przypadku afterAll gwarantuje, że metoda stopMocking zostanie wywołana po wszystkich testach.
Haki Testowe
Vitest udostępnia kilka haków, które można wywołać podczas wykonywania testu, aby oczyścić stan po zakończeniu działania testu.
WARNING
Te haki zgłoszą błąd, jeśli zostaną wywołane poza ciałem testu.
onTestFinished
Ten hak jest zawsze wywoływany po zakończeniu wykonywania testu. Jest wywoływany po hakach afterEach, ponieważ mogą one wpływać na wynik testu. Otrzymuje obiekt TaskResult z aktualnym wynikiem testu.
import { onTestFinished, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});WARNING
Jeśli uruchamiasz testy współbieżnie, zawsze powinieneś używać haka onTestFinished z kontekstu testu, ponieważ Vitest nie śledzi testów współbieżnych w globalnych hakach:
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFinished }) => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});Ten hak jest szczególnie przydatny podczas tworzenia logiki wielokrotnego użytku:
// To może znajdować się w osobnym pliku
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
Ten hak jest zawsze wywoływany w odwrotnej kolejności i nie ma na niego wpływu opcja sequence.hooks.
onTestFailed
Ten hak jest wywoływany tylko po niepowodzeniu testu. Jest wywoływany po hakach afterEach, ponieważ mogą one wpływać na wynik testu. Otrzymuje obiekt TaskResult z aktualnym wynikiem testu. Ten hak jest przydatny do debugowania.
import { onTestFailed, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFailed(e => {
console.log(e.result.errors);
});
db.query('SELECT * FROM users');
});WARNING
Jeśli uruchamiasz testy współbieżnie, zawsze powinieneś używać haka onTestFailed z kontekstu testu, ponieważ Vitest nie śledzi testów współbieżnych w globalnych hakach:
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFailed }) => {
const db = connectDb();
onTestFailed(result => {
console.log(result.errors);
});
db.query('SELECT * FROM users');
});