Dokumentacja API testowego
Poniższe typy są używane w sygnaturach typów poniżej.
type Awaitable<T> = T | PromiseLike<T>;
type TestFunction = () => Awaitable<void>;
interface TestOptions {
/**
* Test zakończy się niepowodzeniem, jeśli jego wykonanie zajmie zbyt dużo czasu.
*/
timeout?: number;
/**
* Ponawia próbę wykonania testu określoną liczbę razy, jeśli się nie powiedzie.
*
* @default 0
*/
retry?: number;
/**
* Ten sam test zostanie powtórzony kilka razy, nawet jeśli za każdym razem się nie powiedzie.
* Jeśli używasz opcji "retry" i test się nie powiedzie, każda próba z "retry" zostanie wykorzystana w każdym cyklu powtórzeń.
* Przydatne do debugowania sporadycznych błędów.
*
* @default 0
*/
repeats?: number;
}Gdy funkcja testowa zwraca obietnicę, program uruchamiający poczeka, aż zostanie ona rozwiązana, aby zebrać wyniki asynchronicznych operacji. Jeśli obietnica zostanie odrzucona, test nie powiedzie się.
TIP
W Jest, TestFunction może być również typu (done: DoneCallback) => void. Jeśli ta forma jest używana, test nie zakończy się, dopóki nie zostanie wywołane done. To samo można osiągnąć za pomocą funkcji async, zobacz sekcję Migration guide Done Callback.
Opcje można zdefiniować, używając łańcuchowego wywoływania metod:
import { test } from 'vitest';
test.skip('test pominięty', () => {
// jakaś logika, która obecnie kończy się niepowodzeniem
});
test.concurrent.skip('pominięty test współbieżny', () => {
// jakaś logika, która obecnie kończy się niepowodzeniem
});Możesz również podać obiekt jako drugi argument:
import { test } from 'vitest';
test('test pominięty', { skip: true }, () => {
// jakaś logika, która obecnie kończy się niepowodzeniem
});
test('pominięty test współbieżny', { skip: true, concurrent: true }, () => {
// jakaś logika, która obecnie kończy się niepowodzeniem
});Obie metody działają dokładnie tak samo. Wybór jednej z nich jest wyłącznie kwestią stylu.
Zauważ, że jeśli podajesz timeout jako ostatni argument, nie możesz już używać obiektu opcji:
import { test } from 'vitest';
// ✅ to działa
test.skip('ciężki test', () => {
// ...
}, 10_000);
// ❌ to nie działa
test(
'ciężki test',
{ skip: true },
() => {
// ...
},
10_000
);Możesz jednak podać timeout w obiekcie:
import { test } from 'vitest';
// ✅ to działa
test('ciężki test', { skip: true, timeout: 10_000 }, () => {
// ...
});test
- Alias:
it
test definiuje zestaw powiązanych oczekiwań. Przyjmuje nazwę testu i funkcję zawierającą asercje do sprawdzenia.
Opcjonalnie możesz podać limit czasu (w milisekundach), aby określić, jak długo czekać przed przerwaniem 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 testu o niestandardowe fixture'y. Spowoduje to zwrócenie nowego obiektu test, który również można rozszerzać, dzięki czemu możesz dodawać więcej fixture'ów lub nadpisywać istniejące, rozszerzając je według potrzeb. Aby uzyskać więcej informacji, zobacz Rozszerzanie kontekstu testu.
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('dodaj 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 z jakiegokolwiek powodu, możesz użyć test.skip, aby je pominąć.
import { assert, test } from 'vitest';
test.skip('test pominięty', () => {
// Test pominięty - nie zgłoszono błędu
assert.equal(Math.sqrt(4), 3);
});Możesz również pominąć test, wywołując skip na obiekcie jego kontekstu dynamicznie:
import { assert, test } from 'vitest';
test('test pominięty', context => {
context.skip();
// Test pominięty - nie zgłoszono błędu
assert.equal(Math.sqrt(4), 3);
});Od Vitest 3.1, jeśli warunek jest dynamiczny, możesz podać go do metody skip jako pierwszy argument:
import { assert, test } from 'vitest';
test('test pominięty', context => {
context.skip(Math.random() < 0.5, 'opcjonalna wiadomość');
// Test pominięty - nie zgłoszono błędu
assert.equal(Math.sqrt(4), 3);
});test.skipIf
- Alias:
it.skipIf
W niektórych przypadkach testy mogą być uruchamiane wielokrotnie w różnych środowiskach, a niektóre z nich mogą być specyficzne dla danego środowiska. Zamiast opakowywać kod testowy w if, możesz użyć test.skipIf, aby pominąć test, gdy warunek jest spełniony.
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.skipIf(isDev)('test tylko dla produkcji', () => {
// ten test jest uruchamiany tylko w środowisku produkcyjnym
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako narzędzia do sprawdzania typów.
test.runIf
- Alias:
it.runIf
Przeciwieństwo test.skipIf.
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.runIf(isDev)('test tylko dla deweloperów', () => {
// ten test jest uruchamiany tylko w środowisku deweloperskim
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako narzędzia do sprawdzania typów.
test.only
- Alias:
it.only
Użyj test.only, aby uruchomić tylko niektóre testy w danej grupie. Jest to przydatne podczas debugowania.
Opcjonalnie możesz podać limit czasu (w milisekundach), aby określić, jak długo czekać przed przerwaniem. Domyślnie jest to 5 sekund i można to skonfigurować globalnie za pomocą testTimeout.
import { assert, test } from 'vitest';
test.only('test', () => {
// Uruchamiany jest tylko ten test (oraz inne oznaczone jako "only")
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łej grupy testów, które mogłyby zanieczyścić/przeładować wynik.
Aby to zrobić, uruchom vitest z określonym plikiem zawierającym interesujące testy.
# vitest interesting.test.tstest.concurrent
- Alias:
it.concurrent
test.concurrent oznacza, że kolejne testy zostaną uruchomione równolegle. Przyjmuje nazwę testu, funkcję asynchroniczną zawierającą testy do wykonania oraz 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, migawki i asercje muszą używać expect z lokalnego kontekstu testu, aby zapewnić prawidłowe przypisanie do 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 narzędzia do sprawdzania typów.
test.sequential
- Alias:
it.sequential
test.sequential oznacza, że test zostanie wykonany sekwencyjnie. Jest to przydatne, jeśli chcesz uruchamiać testy w sekwencji w ramach describe.concurrent lub z opcją --sequence.concurrent w linii komend.
import { describe, test } from 'vitest';
// z opcją konfiguracyjną { sequence: { concurrent: true } }
test('test współbieżny 1', async () => {
/* ... */
});
test('test współbieżny 2', async () => {
/* ... */
});
test.sequential('test sekwencyjny 1', async () => {
/* ... */
});
test.sequential('test sekwencyjny 2', async () => {
/* ... */
});
// w ramach współbieżnej grupy
describe.concurrent('suite', () => {
test('test współbieżny 1', async () => {
/* ... */
});
test('test współbieżny 2', async () => {
/* ... */
});
test.sequential('test sekwencyjny 1', async () => {
/* ... */
});
test.sequential('test sekwencyjny 2', async () => {
/* ... */
});
});test.todo
- Alias:
it.todo
Użyj test.todo, aby oznaczyć testy do późniejszej implementacji. W raporcie zostanie wyświetlony wpis dla tych testów, dzięki czemu będziesz wiedzieć, 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 jawnie wskazać, że asercja nie powiedzie się.
import { expect, test } from 'vitest';
function myAsyncFunc() {
return new Promise(resolve => resolve(1));
}
test.fails('test, który ma się nie powieść', async () => {
await expect(myAsyncFunc()).rejects.toBe(1);
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako narzędzia do sprawdzania typów.
test.each
- Alias:
it.each
TIP
Podczas gdy test.each jest dostarczany dla kompatybilności z Jest, Vitest posiada również test.for z dodatkową funkcją umożliwiającą integrację TestContext.
Użyj test.each, gdy chcesz uruchomić ten sam test z różnymi zmiennymi. Możesz wstrzyknąć parametry z formatowaniem printf do nazwy testu, zgodnie z kolejnością parametrów funkcji testowej.
%s: string%d: number%i: integer%f: floating point value%j: json%o: object%#: indeks przypadku testowego (liczony od 0)%$: indeks przypadku testowego (liczony od 1)%%: pojedynczy znak procentu ('%')
import { expect, test } from 'vitest';
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('dodaj(%i, %i) -> %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// to zwróci
// ✓ dodaj(1, 1) -> 2
// ✓ dodaj(1, 2) -> 3
// ✓ dodaj(2, 1) -> 3Możesz również uzyskać dostęp do właściwości obiektów i elementów tablic za pomocą prefiksu $:
test.each([
{ a: 1, b: 1, expected: 2 },
{ a: 1, b: 2, expected: 3 },
{ a: 2, b: 1, expected: 3 },
])('dodaj($a, $b) -> $expected', ({ a, b, expected }) => {
expect(a + b).toBe(expected);
});
// to zwróci
// ✓ dodaj(1, 1) -> 2
// ✓ dodaj(1, 2) -> 3
// ✓ dodaj(2, 1) -> 3
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('dodaj($0, $1) -> $2', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// to zwróci
// ✓ dodaj(1, 1) -> 2
// ✓ dodaj(1, 2) -> 3
// ✓ dodaj(2, 1) -> 3Możesz również uzyskać dostęp do atrybutów obiektów 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'}
`('dodaj($a.val, $b) -> $expected', ({ a, b, expected }) => {
expect(a.val + b).toBe(expected);
});
// to zwróci
// ✓ dodaj(1, b) -> 1b
// ✓ dodaj(2, b) -> 2b
// ✓ dodaj(3, b) -> 3bPocząwszy od Vitest 0.25.3, możesz również używać tabeli w postaci literału szablonowego.
- Pierwszy wiersz powinien zawierać nazwy kolumn, oddzielone znakiem
|; - Jeden lub więcej kolejnych wierszy danych dostarczonych jako wyrażenia w literałach szablonowych, używając 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 zostanie dodane do $b', ({ a, b, expected }) => {
expect(a + b).toBe(expected);
});TIP
Vitest przetwarza wartości $values metodą format z Chai. Jeśli wartość jest zbyt mocno skrócona, możesz zwiększyć chaiConfig.truncateThreshold w pliku konfiguracyjnym.
WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako narzędzia do sprawdzania typów.
test.for
- Alias:
it.for
Alternatywa dla test.each do dostarczania TestContext.
Różnica od test.each polega na sposobie dostarczania argumentów w postaci tablic. Argumenty niebędące tablicami dla test.for (w tym użycie literałów szablonowych) działają dokładnie tak samo jak dla test.each.
// `each` rozpakowuje elementy tablicy
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('dodaj(%i, %i) -> %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// `for` nie rozpakowuje elementów tablicy (zauważ nawiasy kwadratowe wokół argumentów)
test.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('dodaj(%i, %i) -> %i', ([a, b, expected]) => {
expect(a + b).toBe(expected);
});Drugi argument to TestContext i może być używany na przykład do współbieżnych migawek:
test.concurrent.for([
[1, 1],
[1, 2],
[2, 1],
])('dodaj(%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 określa serię operacji. Vitest uruchamia tę funkcję wielokrotnie, aby przedstawić różne wyniki wydajności.
Vitest używa biblioteki tinybench wewnętrznie, przejmując wszystkie jej opcje, które mogą być użyte 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 wykonania zadania benchmarkowego (w milisekundach).
* @default 500
*/
time?: number;
/**
* Liczba razy, ile zadanie powinno zostać uruchomione, nawet jeśli upłynął czas określony w opcji `time`.
* @default 10
*/
iterations?: number;
/**
* Funkcja zwracająca aktualny znacznik czasu w milisekundach.
*/
now?: () => number;
/**
* Sygnał AbortSignal do przerwania benchmarku.
*/
signal?: AbortSignal;
/**
* Rzuć wyjątek, jeśli zadanie zakończy się niepowodzeniem (zdarzenia nie będą działać, jeśli `throws` jest ustawione na `true`).
*/
throws?: boolean;
/**
* Czas rozgrzewki (milisekundy).
* @default 100ms
*/
warmupTime?: number;
/**
* Iteracje rozgrzewki.
* @default 5
*/
warmupIterations?: number;
/**
* Funkcja setup do wykonania przed każdym zadaniem benchmarkowym (cyklem).
*/
setup?: Hook;
/**
* Funkcja teardown do wykonania po każdym zadaniu benchmarkowym (cyklem).
*/
teardown?: Hook;
}Po uruchomieniu benchmarku, struktura informacji wyjściowych jest następująca:
nazwa hz min max średnia p75 p99 p995 p999 rme próbki
· normalne sortowanie 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, który wystąpił podczas wykonywania zadania.
*/
error?: unknown;
/**
* Całkowity czas (w milisekundach) potrzebny na wykonanie zadania benchmarkowego (cyklu).
*/
totalTime: number;
/**
* Minimalna wartość z próbek.
*/
min: number;
/**
* Maksymalna wartość z próbek.
*/
max: number;
/**
* Liczba operacji na sekundę.
*/
hz: number;
/**
* Czas trwania pojedynczej operacji (w ms).
*/
period: number;
/**
* Próbki czasu trwania każdej iteracji zadania (w ms).
*/
samples: number[];
/**
* Średnia próbek (oszacowanie średniej populacji).
*/
mean: number;
/**
* Wariancja próbek (oszacowanie wariancji populacji).
*/
variance: number;
/**
* Odchylenie standardowe próbek (oszacowanie 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 dla próbek.
*/
critical: number;
/**
* Margines błędu.
*/
moe: number;
/**
* Względny margines błędu.
*/
rme: number;
/**
* Mediana bezwzględnych odchyleń.
*/
mad: number;
/**
* Percentyl p50/mediana.
*/
p50: number;
/**
* Percentyl p75.
*/
p75: number;
/**
* Percentyl p99.
*/
p99: number;
/**
* Percentyl p995.
*/
p995: number;
/**
* Percentyl p999.
*/
p999: number;
}bench.skip
- Typ:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
Możesz użyć składni bench.skip, aby pominąć wykonanie niektórych benchmarków.
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 uruchomić tylko niektóre benchmarki w danej grupie. 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 oznaczyć benchmarki do późniejszej implementacji.
import { bench } from 'vitest';
bench.todo('niezaimplementowany test');describe
Gdy używasz test lub bench na najwyższym poziomie pliku, są one zbierane jako część domyślnej grupy dla tego pliku. Używając describe, możesz zdefiniować nową grupę w bieżącym kontekście, która będzie zawierać powiązane testy lub benchmarki oraz inne zagnieżdżone grupy. Grupy pozwalają na organizowanie testów i benchmarków, dzięki czemu raporty są bardziej czytelne.
// basic.spec.ts
// organizowanie testów
import { describe, expect, test } from 'vitest';
const person = {
isActive: true,
age: 32,
};
describe('osoba', () => {
test('osoba jest zdefiniowana', () => {
expect(person).toBeDefined();
});
test('jest aktywna', () => {
expect(person.isActive).toBeTruthy();
});
test('limit wieku', () => {
expect(person.age).toBeLessThanOrEqual(32);
});
});// basic.bench.ts
// organizowanie benchmarków
import { bench, describe } from 'vitest';
describe('sortowanie', () => {
bench('normalne', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});
bench('odwrotne', () => {
const x = [1, 5, 4, 2, 3];
x.reverse().sort((a, b) => {
return a - b;
});
});
});Możesz również zagnieżdżać bloki describe, jeśli masz hierarchię testów lub benchmarków:
import { describe, expect, test } from 'vitest';
function numberToCurrency(value: number | string) {
if (typeof value !== 'number') {
throw new TypeError('Wartość musi być liczbą');
}
return value
.toFixed(2)
.toString()
.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
describe('numberToCurrency', () => {
describe('dla nieprawidłowej liczby', () => {
test('złożonej z nieliczb, powinna rzucić błąd', () => {
expect(() => numberToCurrency('abc')).toThrowError();
});
});
describe('dla prawidłowej liczby', () => {
test('zwraca prawidłowy format waluty', () => {
expect(numberToCurrency(10000)).toBe('10,000.00');
});
});
});describe.skip
- Alias:
suite.skip
Użyj describe.skip w grupie, aby uniknąć uruchamiania określonego bloku describe.
import { assert, describe, test } from 'vitest';
describe.skip('pominięta grupa', () => {
test('sqrt', () => {
// Grupa pominięta, brak błędu
assert.equal(Math.sqrt(4), 3);
});
});describe.skipIf
- Alias:
suite.skipIf
W niektórych przypadkach grupy testów mogą być uruchamiane wielokrotnie w różnych środowiskach, a niektóre z nich mogą być specyficzne dla danego środowiska. Zamiast opakowywać grupę w if, możesz użyć describe.skipIf, aby pominąć grupę, gdy warunek jest spełniony.
import { describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.skipIf(isDev)('grupa testów tylko dla produkcji', () => {
// ta grupa testów jest uruchamiana tylko w środowisku produkcyjnym
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako narzędzia do 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)('grupa testów tylko dla deweloperów', () => {
// ta grupa testów jest uruchamiana tylko w środowisku deweloperskim
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako narzędzia do sprawdzania typów.
describe.only
- Typ:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
Użyj describe.only, aby uruchomić tylko niektóre grupy testów.
import { assert, describe, test } from 'vitest';
// Uruchamiana jest tylko ta grupa (oraz inne oznaczone jako "only")
describe.only('suite', () => {
test('sqrt', () => {
assert.equal(Math.sqrt(4), 3);
});
});
describe('inna grupa', () => {
// ... zostanie pominięta
});Czasami bardzo przydatne jest uruchamianie testów only w określonym pliku, ignorując wszystkie inne testy z całej grupy testów, które mogłyby zanieczyścić/przeładować wynik.
Aby to zrobić, uruchom vitest z określonym plikiem zawierającym interesujące testy.
# vitest interesting.test.tsdescribe.concurrent
- Alias:
suite.concurrent
describe.concurrent uruchamia wszystkie zagnieżdżone grupy i testy równolegle.
import { describe, test } from 'vitest';
// Wszystkie grupy i testy w tej grupie zostaną uruchomione równolegle
describe.concurrent('suite', () => {
test('test współbieżny 1', async () => {
/* ... */
});
describe('grupa współbieżna 2', async () => {
test('test współbieżny wewnętrzny 1', async () => {
/* ... */
});
test('test współbieżny wewnętrzny 2', async () => {
/* ... */
});
});
test.concurrent('test współbieżny 3', async () => {
/* ... */
});
});.skip, .only i .todo działają z grupami współbieżnymi. Wszystkie poniższe kombinacje są prawidłowe:
describe.concurrent(/* ... */);
describe.skip.concurrent(/* ... */); // lub describe.concurrent.skip(/* ... */)
describe.only.concurrent(/* ... */); // lub describe.concurrent.only(/* ... */)
describe.todo.concurrent(/* ... */); // lub describe.concurrent.todo(/* ... */)Podczas uruchamiania testów współbieżnych, migawki i asercje muszą używać expect z lokalnego kontekstu testu, aby zapewnić prawidłowe przypisanie do testu.
describe.concurrent('suite', () => {
test('test współbieżny 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test('test współbieżny 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako narzędzia do sprawdzania typów.
describe.sequential
- Alias:
suite.sequential
describe.sequential w grupie oznacza, że każdy test zostanie wykonany sekwencyjnie. Jest to przydatne, jeśli chcesz uruchamiać testy w sekwencji w ramach describe.concurrent lub z opcją --sequence.concurrent w linii komend.
import { describe, test } from 'vitest';
describe.concurrent('suite', () => {
test('test współbieżny 1', async () => {
/* ... */
});
test('test współbieżny 2', async () => {
/* ... */
});
describe.sequential('', () => {
test('test sekwencyjny 1', async () => {
/* ... */
});
test('test sekwencyjny 2', async () => {
/* ... */
});
});
});describe.shuffle
- Alias:
suite.shuffle
Vitest zapewnia sposób na uruchamianie wszystkich testów w losowej kolejności za pomocą flagi CLI --sequence.shuffle lub opcji konfiguracyjnej sequence.shuffle. Jeśli jednak chcesz, aby tylko część twojej grupy testów uruchamiała testy w losowej kolejności, możesz oznaczyć ją tą flagą.
import { describe, test } from 'vitest';
// lub describe('suite', { shuffle: true }, ...)
describe.shuffle('suite', () => {
test('losowy test 1', async () => {
/* ... */
});
test('losowy test 2', async () => {
/* ... */
});
test('losowy test 3', async () => {
/* ... */
});
// opcja `shuffle` jest dziedziczona
describe('nadal losowe', () => {
test('losowy 4.1', async () => {
/* ... */
});
test('losowy 4.2', async () => {
/* ... */
});
});
// wyłącz losową kolejność wewnątrz
describe('nie losowe', { shuffle: false }, () => {
test('w kolejności 5.1', async () => {
/* ... */
});
test('w kolejności 5.2', async () => {
/* ... */
});
});
});
// kolejność zależy od opcji sequence.seed w konfiguracji (domyślnie Date.now()).skip, .only i .todo działają z losowymi grupami.
WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako narzędzia do sprawdzania typów.
describe.todo
- Alias:
suite.todo
Użyj describe.todo, aby oznaczyć grupy testów do późniejszej implementacji. W raporcie zostanie wyświetlony wpis dla tych grup, dzięki czemu będziesz wiedzieć, ile testów musisz jeszcze zaimplementować.
// W raporcie zostanie wyświetlony wpis dla tej grupy
describe.todo('niezaimplementowana grupa');describe.each
- Alias:
suite.each
TIP
Podczas gdy describe.each jest dostarczany dla kompatybilności z Jest, Vitest posiada również describe.for, który upraszcza typy argumentów i jest zgodny z test.for.
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 },
])('opis obiektu dodaj($a, $b)', ({ a, b, expected }) => {
test(`zwraca ${expected}`, () => {
expect(a + b).toBe(expected);
});
test(`zwrócona wartość nie powinna być większa od ${expected}`, () => {
expect(a + b).not.toBeGreaterThan(expected);
});
test(`zwrócona wartość nie powinna być mniejsza od ${expected}`, () => {
expect(a + b).not.toBeLessThan(expected);
});
});Począwszy od Vitest 0.25.3, możesz również używać tabeli w postaci literału szablonowego.
- Pierwszy wiersz powinien zawierać nazwy kolumn, oddzielone znakiem
|; - Jeden lub więcej kolejnych wierszy danych dostarczonych jako wyrażenia w literałach szablonowych, używając 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'}
`('opis literału szablonowego dodaj($a, $b)', ({ a, b, expected }) => {
test(`zwraca ${expected}`, () => {
expect(a + b).toBe(expected);
});
});WARNING
Nie możesz używać tej składni, gdy używasz Vitest jako narzędzia do sprawdzania typów.
describe.for
- Alias:
suite.for
Różnica od describe.each polega na sposobie dostarczania argumentów w postaci tablicy. Inne przypadki niebędące tablicami (w tym użycie literałów szablonowych) działają dokładnie tak samo.
// `each` rozpakowuje elementy tablicy
describe.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('dodaj(%i, %i) -> %i', (a, b, expected) => {
test('test', () => {
expect(a + b).toBe(expected);
});
});
// `for` nie rozpakowuje elementów tablicy
describe.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('dodaj(%i, %i) -> %i', ([a, b, expected]) => {
test('test', () => {
expect(a + b).toBe(expected);
});
});Konfiguracja i czyszczenie
Te funkcje pozwalają na wpięcie się w cykl życia testów, aby uniknąć powtarzania kodu konfiguracji i czyszczenia. Stosują się one do bieżącego kontekstu: pliku (jeśli są używane na najwyższym poziomie) lub bieżącej grupy (jeśli znajdują się w bloku describe). Te hooki nie są wywoływane, gdy uruchamiasz Vitest jako narzędzie do sprawdzania 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 zwróci obietnicę, Vitest poczeka na jej rozwiązanie, zanim uruchomi test.
Opcjonalnie możesz przekazać limit czasu (w milisekundach) określający, jak długo czekać przed zakończeniem. Domyślnie jest to 5 sekund.
import { beforeEach } from 'vitest';
beforeEach(async () => {
// Wyczyść zaślepki i dodaj dane testowe przed każdym uruchomieniem testu
await stopMocking();
await addUser({ name: 'John' });
});Tutaj beforeEach zapewnia, że użytkownik zostanie dodany przed każdym testem.
beforeEach akceptuje również opcjonalną funkcję czyszczącą (równoważną afterEach).
import { beforeEach } from 'vitest';
beforeEach(async () => {
// wywoływane raz przed każdym testem
await prepareSomething();
// funkcja czyszcząca, wywoływana raz po każdym testu
return async () => {
await resetSomething();
};
});afterEach
- Typ:
afterEach(fn: () => Awaitable<void>, timeout?: number)
Rejestruje funkcję zwrotną, która zostanie wywołana po zakończeniu każdego testu w bieżącym kontekście. Jeśli funkcja zwróci obietnicę, Vitest poczeka na jej rozwiązanie, zanim będzie kontynuować.
Opcjonalnie możesz podać limit czasu (w milisekundach) określający, jak długo czekać przed zakończeniem. Domyślnie jest to 5 sekund.
import { afterEach } from 'vitest';
afterEach(async () => {
await clearTestingData(); // wyczyść dane testowe po każdym uruchomieniu testu
});Tutaj afterEach zapewnia, że dane testowe zostaną wyczyszczone po każdym uruchomieniu testu.
TIP
Vitest 1.3.0 dodał funkcję zwrotną onTestFinished. Możesz ją wywołać podczas wykonywania testu, aby wyczyścić stan po zakończeniu testu.
beforeAll
- Typ:
beforeAll(fn: () => Awaitable<void>, timeout?: number)
Rejestruje funkcję zwrotną, która zostanie wywołana raz przed rozpoczęciem uruchamiania wszystkich testów w bieżącym kontekście. Jeśli funkcja zwróci obietnicę, Vitest poczeka na jej rozwiązanie, zanim uruchomi testy.
Opcjonalnie możesz podać limit czasu (w milisekundach) określający, jak długo czekać przed zakończeniem. Domyślnie jest to 5 sekund.
import { beforeAll } from 'vitest';
beforeAll(async () => {
await startMocking(); // wywoływane raz przed wszystkimi testami
});Tutaj beforeAll zapewnia, że dane zaślepione zostaną ustawione przed uruchomieniem testów.
beforeAll akceptuje również opcjonalną funkcję czyszczącą (równoważną afterAll).
import { beforeAll } from 'vitest';
beforeAll(async () => {
// wywoływane raz przed wszystkimi testami
await startMocking();
// funkcja czyszcząca, wywoływana raz po wszystkich testach
return async () => {
await stopMocking();
};
});afterAll
- Typ:
afterAll(fn: () => Awaitable<void>, timeout?: number)
Rejestruje funkcję zwrotną, która zostanie wywołana raz po zakończeniu wszystkich testów w bieżącym kontekście. Jeśli funkcja zwróci obietnicę, Vitest poczeka na jej rozwiązanie, zanim będzie kontynuować.
Opcjonalnie możesz podać limit czasu (w milisekundach) określający, jak długo czekać przed zakończeniem. Domyślnie jest to 5 sekund.
import { afterAll } from 'vitest';
afterAll(async () => {
await stopMocking(); // ta metoda zostanie wywołana po uruchomieniu wszystkich testów
});Tutaj afterAll zapewnia, że metoda stopMocking zostanie wywołana po uruchomieniu wszystkich testów.
Hooki testowe
Vitest udostępnia kilka funkcji zwrotnych (hooków), które możesz wywołać podczas wykonywania testu, aby wyczyścić stan po zakończeniu testu.
WARNING
Te hooki zgłoszą błąd, jeśli zostaną wywołane poza ciałem testu.
onTestFinished
Ta funkcja zwrotna jest zawsze wywoływana po zakończeniu testu. Jest wywoływana po funkcjach zwrotnych afterEach, ponieważ mogą one mieć wpływ na wynik testu. Otrzymuje obiekt ExtendedContext tak samo jak beforeEach i afterEach.
import { onTestFinished, test } from 'vitest';
test('wykonuje zapytanie', () => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});WARNING
Jeśli uruchamiasz testy współbieżnie, zawsze powinieneś używać funkcji zwrotnej onTestFinished z kontekstu testu, ponieważ Vitest nie monitoruje testów współbieżnych w globalnych funkcjach zwrotnych:
import { test } from 'vitest';
test.concurrent('wykonuje zapytanie', ({ onTestFinished }) => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});Ta funkcja zwrotna jest szczególnie przydatna podczas tworzenia logiki wielokrotnego użytku:
// to może być w osobnym pliku
function getTestDb() {
const db = connectMockedDb();
onTestFinished(() => db.close());
return db;
}
test('wykonuje zapytanie użytkownika', async () => {
const db = getTestDb();
expect(await db.query('SELECT * from users').perform()).toEqual([]);
});
test('wykonuje zapytanie organizacji', async () => {
const db = getTestDb();
expect(await db.query('SELECT * from organizations').perform()).toEqual([]);
});TIP
Ta funkcja zwrotna jest zawsze wywoływana w odwrotnej kolejności i nie ma na nią wpływu opcja sequence.hooks.
onTestFailed
Ta funkcja zwrotna jest wywoływana tylko po niepowodzeniu testu. Jest wywoływana po funkcjach zwrotnych afterEach, ponieważ mogą one mieć wpływ na wynik testu. Otrzymuje obiekt ExtendedContext tak samo jak beforeEach i afterEach. Ta funkcja zwrotna jest przydatna do debugowania.
import { onTestFailed, test } from 'vitest';
test('wykonuje zapytanie', () => {
const db = connectDb();
onTestFailed(({ task }) => {
console.log(task.result.errors);
});
db.query('SELECT * FROM users');
});WARNING
Jeśli uruchamiasz testy współbieżnie, zawsze powinieneś używać funkcji zwrotnej onTestFailed z kontekstu testu, ponieważ Vitest nie monitoruje testów współbieżnych w globalnych funkcjach zwrotnych:
import { test } from 'vitest';
test.concurrent('wykonuje zapytanie', ({ onTestFailed }) => {
const db = connectDb();
onTestFailed(({ task }) => {
console.log(task.result.errors);
});
db.query('SELECT * FROM users');
});