Test-API-Referenz
Die folgenden Typen werden in den nachstehenden Typensignaturen verwendet:
type Awaitable<T> = T | PromiseLike<T>;
type TestFunction = () => Awaitable<void>;
interface TestOptions {
/**
* Lässt den Test fehlschlagen, wenn die Ausführung zu lange dauert.
*/
timeout?: number;
/**
* Wiederholt den Test eine festgelegte Anzahl von Malen, wenn er fehlschlägt.
*
* @default 0
*/
retry?: number;
/**
* Wiederholt denselben Test mehrfach, auch wenn er jedes Mal fehlschlägt.
* Wenn die Option "retry" aktiviert ist und der Test fehlschlägt, wird jeder Wiederholungsversuch in jedem Zyklus angewendet.
* Nützlich zum Debuggen sporadisch auftretender Fehler.
*
* @default 0
*/
repeats?: number;
}Wenn eine Testfunktion ein Promise zurückgibt, wartet der Testrunner, bis es aufgelöst ist, um asynchrone Erwartungen auszuwerten. Wenn das Promise abgelehnt wird, schlägt der Test fehl.
TIP
In Jest kann TestFunction auch vom Typ (done: DoneCallback) => void sein. Wenn diese Form verwendet wird, wird der Test erst abgeschlossen, wenn done aufgerufen wird. Das Gleiche lässt sich mit einer async-Funktion erreichen, siehe den Abschnitt Migrationsleitfaden Done Callback.
Sie können Optionen definieren, indem Sie Eigenschaften an eine Funktion ketten:
import { test } from 'vitest';
test.skip('skipped test', () => {
// some logic that fails right now
});
test.concurrent.skip('skipped concurrent test', () => {
// some logic that fails right now
});Alternativ können Sie ein Objekt als zweites Argument übergeben:
import { test } from 'vitest';
test('skipped test', { skip: true }, () => {
// some logic that fails right now
});
test('skipped concurrent test', { skip: true, concurrent: true }, () => {
// some logic that fails right now
});Beide Methoden funktionieren identisch. Die Wahl der Methode ist rein stilistischer Natur.
Beachten Sie, dass Sie bei Angabe des Timeouts als letztes Argument keine Optionen mehr verwenden können:
import { test } from 'vitest';
// ✅ this works
test.skip('heavy test', () => {
// ...
}, 10_000);
// ❌ this doesn't work
test(
'heavy test',
{ skip: true },
() => {
// ...
},
10_000
);Sie können jedoch ein Timeout innerhalb des Optionen-Objekts angeben:
import { test } from 'vitest';
// ✅ this works
test('heavy test', { skip: true, timeout: 10_000 }, () => {
// ...
});test
- Alias:
it
test definiert eine Reihe von zusammenhängenden Erwartungen. Es nimmt den Testnamen und eine Funktion entgegen, die die zu testenden Erwartungen enthält.
Optional können Sie ein Timeout (in Millisekunden) angeben, um festzulegen, wie lange vor dem Abbruch gewartet werden soll. Der Standardwert beträgt 5 Sekunden und kann global mit testTimeout konfiguriert werden.
import { expect, test } from 'vitest';
test('should work as expected', () => {
expect(Math.sqrt(4)).toBe(2);
});test.extend
- Alias:
it.extend
Verwenden Sie test.extend, um den Testkontext mit benutzerdefinierten Fixtures zu erweitern. Dies gibt einen neuen test zurück, der ebenfalls erweiterbar ist, sodass Sie weitere Fixtures zusammensetzen oder bestehende überschreiben können, indem Sie sie nach Bedarf erweitern. Weitere Informationen finden Sie unter Testkontext erweitern.
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('add item', ({ todos }) => {
expect(todos.length).toBe(3);
todos.push(4);
expect(todos.length).toBe(4);
});test.skip
- Alias:
it.skip
Wenn Sie bestimmte Tests überspringen möchten, aber den Code aus bestimmten Gründen nicht löschen möchten, können Sie test.skip verwenden, um deren Ausführung zu verhindern.
import { assert, test } from 'vitest';
test.skip('skipped test', () => {
// Test übersprungen, kein Fehler
assert.equal(Math.sqrt(4), 3);
});Sie können Tests auch überspringen, indem Sie skip dynamisch im Kontext aufrufen:
import { assert, test } from 'vitest';
test('skipped test', context => {
context.skip();
// Test übersprungen, kein Fehler
assert.equal(Math.sqrt(4), 3);
});Seit Vitest 3.1 können Sie, wenn die Bedingung unbekannt ist, diese als erstes Argument an die skip-Methode übergeben:
import { assert, test } from 'vitest';
test('skipped test', context => {
context.skip(Math.random() < 0.5, 'optional message');
// Test übersprungen, kein Fehler
assert.equal(Math.sqrt(4), 3);
});test.skipIf
- Alias:
it.skipIf
In einigen Fällen können Tests mehrmals in verschiedenen Umgebungen ausgeführt werden, und einige der Tests könnten umgebungsspezifisch sein. Anstatt den Testcode mit if zu umschließen, können Sie test.skipIf verwenden, um den Test zu überspringen, sobald die Bedingung wahr ist.
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.skipIf(isDev)('prod only test', () => {
// dieser Test läuft nur in der Produktion
});WARNING
Sie können diese Syntax nicht verwenden, wenn Sie Vitest als Typ-Checker verwenden.
test.runIf
- Alias:
it.runIf
Gegenteil von test.skipIf.
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.runIf(isDev)('dev only test', () => {
// dieser Test läuft nur in der Entwicklung
});WARNING
Sie können diese Syntax nicht verwenden, wenn Sie Vitest als Typ-Checker verwenden.
test.only
- Alias:
it.only
Verwenden Sie test.only, um nur bestimmte Tests in einer bestimmten Suite auszuführen. Dies ist nützlich beim Debuggen.
Optional können Sie ein Timeout (in Millisekunden) angeben, um festzulegen, wie lange vor dem Abbruch gewartet werden soll. Der Standardwert beträgt 5 Sekunden und kann global mit testTimeout konfiguriert werden.
import { assert, test } from 'vitest';
test.only('test', () => {
// Nur dieser Test (und andere mit "only" markierte) werden ausgeführt
assert.equal(Math.sqrt(4), 2);
});Manchmal ist es sehr nützlich, only-Tests in einer bestimmten Datei auszuführen und alle anderen Tests der gesamten Testsuite zu ignorieren, die die Ausgabe unübersichtlich machen.
Führen Sie dazu vitest mit der spezifischen Datei aus, die die betreffenden Tests enthält.
# vitest interesting.test.tstest.concurrent
- Alias:
it.concurrent
test.concurrent markiert Tests zur parallelen Ausführung. Es empfängt den Testnamen, eine asynchrone Funktion, die die Testlogik enthält, und ein optionales Timeout (in Millisekunden).
import { describe, test } from 'vitest';
// Die beiden mit "concurrent" markierten Tests werden parallel ausgeführt
describe('suite', () => {
test('serial test', async () => {
/* ... */
});
test.concurrent('concurrent test 1', async () => {
/* ... */
});
test.concurrent('concurrent test 2', async () => {
/* ... */
});
});test.skip, test.only und test.todo funktionieren mit parallelen Tests. Alle folgenden Kombinationen sind gültig:
test.concurrent(/* ... */);
test.skip.concurrent(/* ... */); // oder test.concurrent.skip(/* ... */)
test.only.concurrent(/* ... */); // oder test.concurrent.only(/* ... */)
test.todo.concurrent(/* ... */); // oder test.concurrent.todo(/* ... */)Beim Ausführen von parallelen Tests müssen Snapshots und Assertions expect aus dem lokalen Testkontext verwenden, um sicherzustellen, dass der richtige Test erkannt wird.
test.concurrent('test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test.concurrent('test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});WARNING
Sie können diese Syntax nicht verwenden, wenn Sie Vitest als Typ-Checker verwenden.
test.sequential
- Alias:
it.sequential
test.sequential markiert einen Test als sequenziell. Dies ist nützlich, wenn Sie Tests innerhalb von describe.concurrent oder mit der Befehlsoption --sequence.concurrent nacheinander ausführen möchten.
import { describe, test } from 'vitest';
// mit Konfigurationsoption { 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 () => {
/* ... */
});
// innerhalb einer parallelen Suite
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
Verwenden Sie test.todo, um Platzhalter für Tests zu erstellen, die später implementiert werden sollen. Ein Eintrag wird im Bericht angezeigt, damit Sie wissen, wie viele Tests Sie noch implementieren müssen.
// Ein Eintrag wird im Bericht für diesen Test angezeigt
test.todo('unimplemented test');test.fails
- Alias:
it.fails
Verwenden Sie test.fails, um ausdrücklich zu kennzeichnen, dass eine Assertion fehlschlagen wird.
import { expect, test } from 'vitest';
function myAsyncFunc() {
return new Promise(resolve => resolve(1));
}
test.fails('fail test', async () => {
await expect(myAsyncFunc()).rejects.toBe(1);
});WARNING
Sie können diese Syntax nicht verwenden, wenn Sie Vitest als Typ-Checker verwenden.
test.each
- Alias:
it.each
TIP
Während test.each für die Jest-Kompatibilität bereitgestellt wird, hat Vitest auch test.for mit einer zusätzlichen Funktion zur Integration von TestContext.
Verwenden Sie test.each, wenn Sie denselben Test mit verschiedenen Variablen ausführen müssen. Sie können Parameter mit printf-Formatierung im Testnamen in der Reihenfolge der Testfunktionsparameter einfügen.
%s: Zeichenkette%d: Zahl%i: Ganzzahl%f: Gleitkommazahl%j: JSON%o: Objekt%#: 0-basierter Index des Testfalls%$: 1-basierter Index des Testfalls%%: einzelnes Prozentzeichen ('%')
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);
});
// this will return
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3Sie können auch auf Objekteigenschaften und Array-Elemente mit dem Präfix $ zugreifen:
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);
});
// this will return
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add($0, $1) -> $2', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// this will return
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3Sie können auch auf Objektattribute mit . zugreifen, wenn Sie Objekte als Argumente verwenden:
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);
});
// this will return
// ✓ add(1, b) -> 1b
// ✓ add(2, b) -> 2b
// ✓ add(3, b) -> 3bAb Vitest 0.25.3 können Sie auch eine Template-String-Tabelle verwenden.
- Die erste Zeile sollte Spaltennamen enthalten, getrennt durch
|; - Eine oder mehrere nachfolgende Zeilen mit Daten, die als Template-Literal-Ausdrücke mit der
${value}-Syntax bereitgestellt werden.
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'}
`('returns $expected when $a is added $b', ({ a, b, expected }) => {
expect(a + b).toBe(expected);
});TIP
Vitest formatiert $values mit der Chai format-Methode. Wenn der Wert zu stark gekürzt wird, können Sie chaiConfig.truncateThreshold in Ihrer Konfigurationsdatei erhöhen.
WARNING
Sie können diese Syntax nicht verwenden, wenn Sie Vitest als Typ-Checker verwenden.
test.for
- Alias:
it.for
Alternative zu test.each, um TestContext bereitzustellen.
Der Unterschied zu test.each liegt in der Art und Weise, wie Arrays in den Argumenten übergeben werden. Argumente, die keine Arrays sind (einschließlich der Verwendung von Template-Strings), funktionieren bei test.for genau wie bei test.each.
// `each` spreads arrays
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// `for` doesn't spread arrays (notice the square brackets around the arguments)
test.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => {
expect(a + b).toBe(expected);
});Das 2. Argument ist TestContext und kann beispielsweise für parallele Snapshots verwendet werden:
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 definiert einen Benchmark. Im Kontext von Vitest ist ein Benchmark eine Funktion, die eine Reihe von Operationen definiert. Vitest führt diese Funktion mehrmals aus, um verschiedene Leistungsergebnisse anzuzeigen.
Vitest verwendet intern die Bibliothek tinybench und erbt alle ihre Optionen, die als drittes Argument verwendet werden können.
import { bench } from 'vitest';
bench(
'normal sorting',
() => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
},
{ time: 1000 }
);export interface Options {
/**
* Zeit, die für die Ausführung einer Benchmark-Aufgabe benötigt wird (Millisekunden).
* @default 500
*/
time?: number;
/**
* Anzahl der Wiederholungen, die eine Aufgabe ausführen soll, selbst wenn die Zeitoption bereits erreicht wurde.
* @default 10
*/
iterations?: number;
/**
* Funktion zum Abrufen des aktuellen Zeitstempels in Millisekunden.
*/
now?: () => number;
/**
* Ein AbortSignal zum Abbrechen des Benchmarks.
*/
signal?: AbortSignal;
/**
* Wirft einen Fehler, wenn eine Aufgabe fehlschlägt (Ereignisse funktionieren nicht, wenn aktiviert).
*/
throws?: boolean;
/**
* Aufwärmzeit (Millisekunden).
* @default 100ms
*/
warmupTime?: number;
/**
* Aufwärm-Iterationen.
* @default 5
*/
warmupIterations?: number;
/**
* Setup-Funktion, die vor jeder Benchmark-Aufgabe (Zyklus) ausgeführt wird.
*/
setup?: Hook;
/**
* Teardown-Funktion, die nach jeder Benchmark-Aufgabe (Zyklus) ausgeführt wird.
*/
teardown?: Hook;
}Nachdem der Testfall ausgeführt wurde, sind die Informationen zur Ausgabestruktur wie folgt:
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 {
/*
* der letzte Fehler, der während der Ausführung der Aufgabe geworfen wurde
*/
error?: unknown;
/**
* Die Zeit in Millisekunden, die für die Ausführung der Benchmark-Aufgabe (Zyklus) benötigt wird.
*/
totalTime: number;
/**
* der minimale Wert in den Stichproben
*/
min: number;
/**
* der maximale Wert in den Stichproben
*/
max: number;
/**
* die Anzahl der Operationen pro Sekunde
*/
hz: number;
/**
* wie lange jede Operation dauert (ms)
*/
period: number;
/**
* Aufgabenstichproben der Zeit jeder Aufgabeniteration (ms)
*/
samples: number[];
/**
* Stichprobenmittelwert (Schätzung des Populationsmittelwerts)
*/
mean: number;
/**
* Stichprobenvarianz (Schätzung der Populationsvarianz)
*/
variance: number;
/**
* Stichprobenstandardabweichung (Schätzung der Populationsstandardabweichung)
*/
sd: number;
/**
* Standardfehler des Mittelwerts (auch bekannt als die Standardabweichung der Stichprobenverteilung des Stichprobenmittelwerts, kurz SEM)
*/
sem: number;
/**
* Freiheitsgrade
*/
df: number;
/**
* kritischer Wert der Stichproben
*/
critical: number;
/**
* Fehlermarge
*/
moe: number;
/**
* relative Fehlermarge
*/
rme: number;
/**
* Median der absoluten Abweichung
*/
mad: number;
/**
* p50-Perzentil (Median)
*/
p50: number;
/**
* p75-Perzentil
*/
p75: number;
/**
* p99-Perzentil
*/
p99: number;
/**
* p995-Perzentil
*/
p995: number;
/**
* p999-Perzentil
*/
p999: number;
}bench.skip
- Typ:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
Sie können die Methode bench.skip verwenden, um die Ausführung bestimmter Benchmarks zu überspringen.
import { bench } from 'vitest';
bench.skip('normal sorting', () => {
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
Verwenden Sie bench.only, um nur bestimmte Benchmarks in einer bestimmten Suite auszuführen. Dies ist nützlich beim Debuggen.
import { bench } from 'vitest';
bench.only('normal sorting', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});bench.todo
- Typ:
(name: string | Function) => void
Verwenden Sie bench.todo, um Platzhalter für Benchmarks zu erstellen, die später implementiert werden sollen.
import { bench } from 'vitest';
bench.todo('unimplemented test');describe
Wenn Sie test oder bench auf oberster Ebene einer Datei verwenden, werden diese als Teil der impliziten Suite für diese Datei gesammelt. Mit describe können Sie eine neue Suite im aktuellen Kontext definieren, als Satz verwandter Tests oder Benchmarks und anderer verschachtelter Suiten. Eine Suite ermöglicht es Ihnen, Ihre Tests und Benchmarks zu organisieren, damit Berichte übersichtlicher sind.
// basic.spec.ts
// Organisieren von Tests
import { describe, expect, test } from 'vitest';
const person = {
isActive: true,
age: 32,
};
describe('person', () => {
test('person ist definiert', () => {
expect(person).toBeDefined();
});
test('ist aktiv', () => {
expect(person.isActive).toBeTruthy();
});
test('Altersgrenze', () => {
expect(person.age).toBeLessThanOrEqual(32);
});
});// basic.bench.ts
// Organisieren von Benchmarks
import { bench, describe } from 'vitest';
describe('sortieren', () => {
bench('normal', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});
bench('umkehren', () => {
const x = [1, 5, 4, 2, 3];
x.reverse().sort((a, b) => {
return a - b;
});
});
});Sie können auch describe-Blöcke verschachteln, wenn Sie eine Hierarchie von Tests oder Benchmarks haben:
import { describe, expect, test } from 'vitest';
function numberToCurrency(value: number | string) {
if (typeof value !== 'number') {
throw new TypeError('Der Wert muss eine Zahl sein');
}
return value
.toFixed(2)
.toString()
.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
describe('numberToCurrency', () => {
describe('bei einer ungültigen Zahl', () => {
test('aus Nicht-Zahlen sollte ein Fehler geworfen werden', () => {
expect(() => numberToCurrency('abc')).toThrowError();
});
});
describe('bei einer gültigen Zahl', () => {
test('gibt das korrekte Währungsformat zurück', () => {
expect(numberToCurrency(10000)).toBe('10,000.00');
});
});
});describe.skip
- Alias:
suite.skip
Verwenden Sie describe.skip in einer Suite, um die Ausführung eines bestimmten describe-Blocks zu vermeiden.
import { assert, describe, test } from 'vitest';
describe.skip('übersprungene Suite', () => {
test('sqrt', () => {
// Suite übersprungen, kein Fehler
assert.equal(Math.sqrt(4), 3);
});
});describe.skipIf
- Alias:
suite.skipIf
In einigen Fällen möchten Sie Suiten mehrmals mit verschiedenen Umgebungen ausführen, und einige der Suiten sind möglicherweise umgebungsspezifisch. Anstatt die Suite in ein if zu umschließen, können Sie describe.skipIf verwenden, um die Suite zu überspringen, wann immer die Bedingung wahr (truthy) ist.
import { describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.skipIf(isDev)('Nur-Prod-Test-Suite', () => {
// diese Test-Suite wird nur in der Produktion ausgeführt
});WARNING
Sie können diese Syntax nicht verwenden, wenn Sie Vitest als Typchecker verwenden.
describe.runIf
- Alias:
suite.runIf
Das Gegenteil von describe.skipIf.
import { assert, describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.runIf(isDev)('Nur-Dev-Test-Suite', () => {
// diese Test-Suite wird nur in der Entwicklung ausgeführt
});WARNING
Sie können diese Syntax nicht verwenden, wenn Sie Vitest als Typchecker verwenden.
describe.only
- Typ:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
Verwenden Sie describe.only, um nur bestimmte Suiten auszuführen.
import { assert, describe, test } from 'vitest';
// Nur diese Suite (und andere mit "only" markierte) werden ausgeführt
describe.only('suite', () => {
test('sqrt', () => {
assert.equal(Math.sqrt(4), 3);
});
});
describe('andere Suite', () => {
// ... wird übersprungen
});Manchmal ist es sehr nützlich, only-Tests in einer bestimmten Datei auszuführen, wobei alle anderen Tests aus der gesamten Test-Suite ignoriert werden, die die Ausgabe verschmutzen.
Um dies zu tun, führen Sie vitest mit der spezifischen Datei aus, die die fraglichen Tests enthält.
# vitest interesting.test.tsdescribe.concurrent
- Alias:
suite.concurrent
describe.concurrent führt alle inneren Suiten und Tests parallel aus.
import { describe, test } from 'vitest';
// Alle Suiten und Tests in dieser Suite werden parallel ausgeführt
describe.concurrent('suite', () => {
test('paralleler Test 1', async () => {
/* ... */
});
describe('parallele Suite 2', async () => {
test('innerer paralleler Test 1', async () => {
/* ... */
});
test('innerer paralleler Test 2', async () => {
/* ... */
});
});
test.concurrent('paralleler Test 3', async () => {
/* ... */
});
});.skip, .only und .todo funktionieren mit parallelen Suiten. Alle folgenden Kombinationen sind gültig:
describe.concurrent(/* ... */);
describe.skip.concurrent(/* ... */); // oder describe.concurrent.skip(/* ... */)
describe.only.concurrent(/* ... */); // oder describe.concurrent.only(/* ... */)
describe.todo.concurrent(/* ... */); // oder describe.concurrent.todo(/* ... */)Bei der Ausführung paralleler Tests müssen Snapshots und Assertions expect aus dem lokalen Test Context verwenden, um sicherzustellen, dass der richtige Test erkannt wird.
describe.concurrent('suite', () => {
test('paralleler Test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test('paralleler Test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
});WARNING
Sie können diese Syntax nicht verwenden, wenn Sie Vitest als Typchecker verwenden.
describe.sequential
- Alias:
suite.sequential
describe.sequential in einer Suite markiert jeden Test als sequenziell. Dies ist nützlich, wenn Sie Tests innerhalb von describe.concurrent oder mit der Kommandozeilenoption --sequence.concurrent sequenziell ausführen möchten.
import { describe, test } from 'vitest';
describe.concurrent('suite', () => {
test('paralleler Test 1', async () => {
/* ... */
});
test('paralleler Test 2', async () => {
/* ... */
});
describe.sequential('', () => {
test('sequenzieller Test 1', async () => {
/* ... */
});
test('sequenzieller Test 2', async () => {
/* ... */
});
});
});describe.shuffle
- Alias:
suite.shuffle
Vitest bietet eine Möglichkeit, alle Tests in zufälliger Reihenfolge auszuführen, entweder über das CLI-Flag --sequence.shuffle oder die Konfigurationsoption sequence.shuffle. Wenn Sie jedoch nur einen Teil Ihrer Test-Suite in zufälliger Reihenfolge ausführen möchten, können Sie diesen Teil mit diesem Flag markieren.
import { describe, test } from 'vitest';
// oder describe('suite', { shuffle: true }, ...)
describe.shuffle('suite', () => {
test('zufälliger Test 1', async () => {
/* ... */
});
test('zufälliger Test 2', async () => {
/* ... */
});
test('zufälliger Test 3', async () => {
/* ... */
});
// `shuffle` wird vererbt
describe('immer noch zufällig', () => {
test('zufällig 4.1', async () => {
/* ... */
});
test('zufällig 4.2', async () => {
/* ... */
});
});
// Deaktivieren von Shuffle innen
describe('nicht zufällig', { shuffle: false }, () => {
test('in Reihenfolge 5.1', async () => {
/* ... */
});
test('in Reihenfolge 5.2', async () => {
/* ... */
});
});
});
// Die Reihenfolge hängt von der sequence.seed-Option in der Konfiguration ab (standardmäßig Date.now()).skip, .only und .todo funktionieren mit zufälligen Suiten.
WARNING
Sie können diese Syntax nicht verwenden, wenn Sie Vitest als Typchecker verwenden.
describe.todo
- Alias:
suite.todo
Verwenden Sie describe.todo, um Suiten, die später implementiert werden müssen, als Platzhalter zu definieren. Ein Eintrag wird im Bericht für die Tests angezeigt, sodass Sie wissen, wie viele Tests Sie noch implementieren müssen.
// Ein Eintrag wird im Bericht für diese Suite angezeigt
describe.todo('nicht implementierte Suite');describe.each
- Alias:
suite.each
TIP
Während describe.each zur Jest-Kompatibilität bereitgestellt wird, besitzt Vitest auch describe.for, was die Argumenttypen vereinfacht und mit test.for übereinstimmt.
Verwenden Sie describe.each, wenn Sie mehr als einen Test haben, der von denselben Daten abhängt.
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(`gibt ${expected} zurück`, () => {
expect(a + b).toBe(expected);
});
test(`der zurückgegebene Wert sollte nicht größer als ${expected} sein`, () => {
expect(a + b).not.toBeGreaterThan(expected);
});
test(`der zurückgegebene Wert sollte nicht kleiner als ${expected} sein`, () => {
expect(a + b).not.toBeLessThan(expected);
});
});Seit Vitest 0.25.3 können Sie auch Tabellen mit Vorlagen-Strings verwenden.
- Die erste Zeile sollte Spaltennamen enthalten, getrennt durch
|; - Eine oder mehrere nachfolgende Datenzeilen, die als Vorlagenliteralausdrücke im Format
${Wert}angegeben werden.
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(`gibt ${expected} zurück`, () => {
expect(a + b).toBe(expected);
});
});WARNING
Sie können diese Syntax nicht verwenden, wenn Sie Vitest als Typchecker verwenden.
describe.for
- Alias:
suite.for
Der Unterschied zu describe.each liegt darin, wie der Array-Fall in den Argumenten bereitgestellt wird. Andere Nicht-Array-Fälle (einschließlich der Verwendung von Vorlagen-Strings) funktionieren exakt gleich.
// `each` entpackt den Array-Fall
describe.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
test('test', () => {
expect(a + b).toBe(expected);
});
});
// `for` entpackt den Array-Fall nicht
describe.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => {
test('test', () => {
expect(a + b).toBe(expected);
});
});Setup und Teardown
Diese Funktionen ermöglichen es Ihnen, in den Lebenszyklus von Tests einzugreifen, um die Wiederholung von Setup- und Teardown-Code zu vermeiden. Sie gelten für den aktuellen Kontext: die Datei, wenn sie auf oberster Ebene verwendet werden, oder die aktuelle Suite, wenn sie sich innerhalb eines describe-Blocks befinden. Diese Hooks werden nicht aufgerufen, wenn Vitest als Typ-Checker ausgeführt wird.
beforeEach
- Typ:
beforeEach(fn: () => Awaitable<void>, timeout?: number)
Registriert einen Callback, der vor jedem Test im aktuellen Kontext ausgeführt wird. Wenn die Funktion ein Promise zurückgibt, wartet Vitest, bis das Promise aufgelöst wurde, bevor der Test ausgeführt wird.
Optional können Sie ein Timeout (in Millisekunden) angeben, das festlegt, wie lange gewartet werden soll, bevor der Test abgebrochen wird. Der Standardwert beträgt 5 Sekunden.
import { beforeEach } from 'vitest';
beforeEach(async () => {
// Mocks löschen und Testdaten hinzufügen vor jeder Testausführung
await stopMocking();
await addUser({ name: 'John' });
});Hier sorgt beforeEach dafür, dass ein Benutzer vor jedem Test hinzugefügt wird.
beforeEach akzeptiert auch eine optionale Bereinigungsfunktion (entspricht afterEach).
import { beforeEach } from 'vitest';
beforeEach(async () => {
// einmal vor jeder Testausführung aufgerufen
await prepareSomething();
// Bereinigungsfunktion, einmal nach jeder Testausführung aufgerufen
return async () => {
await resetSomething();
};
});afterEach
- Typ:
afterEach(fn: () => Awaitable<void>, timeout?: number)
Registriert einen Callback, der nach Abschluss jedes Tests im aktuellen Kontext aufgerufen wird. Wenn die Funktion ein Promise zurückgibt, wartet Vitest, bis das Promise aufgelöst wurde, bevor es fortfährt.
Optional können Sie ein Timeout (in Millisekunden) angeben, das festlegt, wie lange gewartet werden soll, bevor der Test abgebrochen wird. Der Standardwert beträgt 5 Sekunden.
import { afterEach } from 'vitest';
afterEach(async () => {
await clearTestingData(); // Testdaten nach jedem Test löschen
});Hier sorgt afterEach dafür, dass die Testdaten nach jedem Test gelöscht werden.
TIP
Vitest 1.3.0 hat den Hook onTestFinished hinzugefügt. Sie können ihn während der Testausführung aufrufen, um den Zustand nach Abschluss des Tests zu bereinigen.
beforeAll
- Typ:
beforeAll(fn: () => Awaitable<void>, timeout?: number)
Registriert einen Callback, der einmal aufgerufen wird, bevor alle Tests im aktuellen Kontext ausgeführt werden. Wenn die Funktion ein Promise zurückgibt, wartet Vitest, bis das Promise aufgelöst wurde, bevor die Tests ausgeführt werden.
Optional können Sie ein Timeout (in Millisekunden) angeben, das festlegt, wie lange gewartet werden soll, bevor der Test abgebrochen wird. Der Standardwert beträgt 5 Sekunden.
import { beforeAll } from 'vitest';
beforeAll(async () => {
await startMocking(); // einmal aufgerufen, bevor alle Tests ausgeführt werden
});Hier stellt beforeAll sicher, dass die Mock-Daten vor der Testausführung eingerichtet werden.
beforeAll akzeptiert auch eine optionale Bereinigungsfunktion (entspricht afterAll).
import { beforeAll } from 'vitest';
beforeAll(async () => {
// einmal aufgerufen, bevor alle Tests ausgeführt werden
await startMocking();
// Bereinigungsfunktion, einmal nach allen Tests aufgerufen
return async () => {
await stopMocking();
};
});afterAll
- Typ:
afterAll(fn: () => Awaitable<void>, timeout?: number)
Registriert einen Callback, der einmal aufgerufen wird, nachdem alle Tests im aktuellen Kontext ausgeführt wurden. Wenn die Funktion ein Promise zurückgibt, wartet Vitest, bis das Promise aufgelöst wurde, bevor es fortfährt.
Optional können Sie ein Timeout (in Millisekunden) angeben, das festlegt, wie lange gewartet werden soll, bevor der Test abgebrochen wird. Der Standardwert beträgt 5 Sekunden.
import { afterAll } from 'vitest';
afterAll(async () => {
await stopMocking(); // diese Methode wird aufgerufen, nachdem alle Tests ausgeführt wurden
});Hier stellt afterAll sicher, dass die Methode stopMocking aufgerufen wird, nachdem alle Tests ausgeführt wurden.
Test-Hooks
Vitest bietet einige Hooks, die Sie während der Testausführung aufrufen können, um den Zustand zu bereinigen, nachdem der Test abgeschlossen ist.
WARNING
Diese Hooks werfen einen Fehler, wenn sie außerhalb des Testkörpers aufgerufen werden.
onTestFinished
Dieser Hook wird immer aufgerufen, nachdem der Test abgeschlossen ist. Er wird nach den afterEach-Hooks aufgerufen, da diese das Testergebnis beeinflussen können. Er empfängt ein ExtendedContext-Objekt wie beforeEach und afterEach.
import { onTestFinished, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});WARNING
Wenn Sie Tests parallel ausführen, sollten Sie den onTestFinished-Hook immer aus dem Testkontext verwenden, da Vitest parallele Tests in globalen Hooks nicht verfolgt:
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFinished }) => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});Dieser Hook ist besonders nützlich zur Erstellung wiederverwendbarer Logik:
// this can be in a separate file
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
Dieser Hook wird immer in umgekehrter Reihenfolge aufgerufen und ist nicht von der Option sequence.hooks betroffen.
onTestFailed
Dieser Hook wird nur aufgerufen, nachdem der Test fehlgeschlagen ist. Er wird nach den afterEach-Hooks aufgerufen, da diese das Testergebnis beeinflussen können. Er empfängt ein ExtendedContext-Objekt wie beforeEach und afterEach. Dieser Hook ist nützlich zum Debuggen.
import { onTestFailed, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFailed(({ task }) => {
console.log(task.result.errors);
});
db.query('SELECT * FROM users');
});WARNING
Wenn Sie Tests parallel ausführen, sollten Sie den onTestFailed-Hook immer aus dem Testkontext verwenden, da Vitest parallele Tests in globalen Hooks nicht verfolgt:
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFailed }) => {
const db = connectDb();
onTestFailed(({ task }) => {
console.log(task.result.errors);
});
db.query('SELECT * FROM users');
});