Funktionen
- Nutzung der Vite-Konfiguration, Transformatoren, Resolver und Plugins
- Ausführung von Tests mit derselben Konfiguration wie Ihre Anwendung
- Intelligenter und sofortiger Überwachungsmodus, vergleichbar mit HMR für Tests
- Komponententests für Vue, React, Svelte, Lit, Marko und weitere Frameworks
- Standardmäßige Unterstützung für TypeScript und JSX
- ESM-First-Ansatz, Top-Level-Await
- Multithreading mit Workern über Tinypool
- Benchmarking-Unterstützung mit Tinybench
- Filterung, Zeitüberschreitungen und parallele Ausführung für Suiten und Tests
- Projektunterstützung
- Jest-kompatible Snapshots
- Chai ist für Assertions integriert und bietet Jest expect-kompatible APIs
- Tinyspy ist zum Mocken integriert
- happy-dom oder jsdom für DOM-Mocking
- Browser-Modus zur Ausführung von Komponententests im Browser
- Codeabdeckung über v8 oder istanbul
- Rust-ähnliche In-Source-Tests
- Typentests über expect-type
- Sharding-Unterstützung
- Meldung unbehandelter Fehler
Gemeinsame Konfiguration zwischen Test, Entwicklung und Build
Vitest nutzt die Konfiguration, Transformatoren, Resolver und Plugins von Vite. Dadurch können Sie dieselbe Konfiguration wie in Ihrer Anwendung verwenden, um Tests auszuführen.
Erfahren Sie mehr unter Vitest konfigurieren.
Watch-Modus
$ vitest
Wenn Sie Ihren Quellcode oder Testdateien ändern, durchsucht Vitest intelligent den Modulgraphen und führt nur die relevanten Tests erneut aus, ähnlich der Funktionsweise von HMR in Vite!
vitest
startet standardmäßig im Entwicklungsmodus im Watch-Modus
. In CI-Umgebungen (wenn process.env.CI
gesetzt ist) wechselt es intelligent in den Run-Modus
. Sie können vitest watch
oder vitest run
verwenden, um den gewünschten Modus explizit festzulegen.
Starten Sie Vitest mit dem --standalone
-Flag, um es im Hintergrund laufen zu lassen. In diesem Modus werden keine Tests ausgeführt, bis sich die entsprechenden Dateien ändern. Vitest führt keine Tests aus, wenn der Quellcode geändert wird, es sei denn, der Test, der die Quelle importiert, wurde bereits ausgeführt.
Gängige Web-Idiome Out-Of-The-Box
Standardmäßige Unterstützung für ES-Module, TypeScript, JSX und PostCSS.
Threads
Standardmäßig führt Vitest Testdateien in mehreren Prozessen mittels node:child_process
über Tinypool (einem leichtgewichtigen Fork von Piscina) aus, wodurch Tests gleichzeitig ausgeführt werden können. Wenn Sie Ihre Testsuite noch weiter beschleunigen möchten, können Sie die Option --pool=threads
aktivieren, um Tests mit node:worker_threads
auszuführen (beachten Sie, dass einige Pakete mit dieser Einrichtung möglicherweise nicht funktionieren).
Um Tests in einem einzigen Thread oder Prozess auszuführen, siehe poolOptions
.
Vitest isoliert auch die Umgebung jeder Datei, sodass Umgebungsänderungen in einer Datei keine Auswirkungen auf andere Dateien haben. Die Isolation kann durch Übergabe von --no-isolate
an die CLI deaktiviert werden (dies geht jedoch zulasten der Korrektheit und zugunsten der Ausführungsleistung).
Testfilterung
Vitest bietet viele Möglichkeiten, die auszuführenden Tests einzugrenzen, um das Testen zu beschleunigen und Ihnen die Konzentration auf die Entwicklung zu ermöglichen.
Erfahren Sie mehr über Testfilterung.
Tests gleichzeitig ausführen
Verwenden Sie .concurrent
in aufeinanderfolgenden Tests, um sie parallel zu starten.
import { describe, it } from 'vitest';
// Die beiden mit concurrent markierten Tests werden parallel gestartet
describe('suite', () => {
it('serial test', async () => {
/* ... */
});
it.concurrent('concurrent test 1', async ({ expect }) => {
/* ... */
});
it.concurrent('concurrent test 2', async ({ expect }) => {
/* ... */
});
});
Wenn Sie .concurrent
auf eine Suite anwenden, wird jeder Test darin parallel gestartet.
import { describe, it } from 'vitest';
// Alle Tests innerhalb dieser Suite werden parallel gestartet
describe.concurrent('suite', () => {
it('concurrent test 1', async ({ expect }) => {
/* ... */
});
it('concurrent test 2', async ({ expect }) => {
/* ... */
});
it.concurrent('concurrent test 3', async ({ expect }) => {
/* ... */
});
});
Sie können auch .skip
, .only
und .todo
mit parallelen Suiten und Tests verwenden. Lesen Sie mehr in der API-Referenz.
WARNING
Beim Ausführen paralleler Tests müssen Snapshots und Assertions expect
aus dem lokalen Testkontext verwenden, um sicherzustellen, dass der richtige Test erkannt wird.
Snapshot
Jest-kompatible Snapshot-Unterstützung.
import { expect, it } from 'vitest';
it('renders correctly', () => {
const result = render();
expect(result).toMatchSnapshot();
});
Erfahren Sie mehr unter Snapshot.
Chai und Jest expect
-Kompatibilität
Chai ist für Assertions integriert und bietet Jest expect
-kompatible APIs.
Beachten Sie, dass, wenn Sie Bibliotheken von Drittanbietern verwenden, die Matcher hinzufügen, das Setzen von test.globals
auf true
eine bessere Kompatibilität bietet.
Mocking
Tinyspy ist für Mocking mit jest
-kompatiblen APIs auf dem vi
-Objekt integriert.
import { expect, vi } from 'vitest';
const fn = vi.fn();
fn('hello', 1);
expect(vi.isMockFunction(fn)).toBe(true);
expect(fn.mock.calls[0]).toEqual(['hello', 1]);
fn.mockImplementation((arg: string) => arg);
fn('world', 2);
expect(fn.mock.results[1].value).toBe('world');
Vitest unterstützt sowohl happy-dom als auch jsdom für das Mocking von DOM- und Browser-APIs. Sie sind nicht in Vitest enthalten, Sie müssen sie separat installieren:
$ npm i -D happy-dom
$ npm i -D jsdom
Danach ändern Sie die Option environment
in Ihrer Konfigurationsdatei:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'happy-dom', // oder 'jsdom', 'node'
},
});
Erfahren Sie mehr unter Mocking.
Coverage
Vitest unterstützt native Codeabdeckung über v8
und instrumentierte Codeabdeckung über istanbul
.
{
"scripts": {
"test": "vitest",
"coverage": "vitest run --coverage"
}
}
Erfahren Sie mehr unter Coverage.
In-Source-Testing
Vitest bietet auch eine Möglichkeit, Tests innerhalb Ihres Quellcodes direkt mit der Implementierung auszuführen, ähnlich wie bei Rusts Modultests.
Dadurch teilen sich die Tests denselben Closure wie die Implementierungen und können private Zustände testen, ohne sie zu exportieren. Gleichzeitig wird die Feedbackschleife für die Entwicklung verkürzt.
// die Implementierung
export function add(...args: number[]): number {
return args.reduce((a, b) => a + b, 0);
}
// In-Source-Testsuiten
if (import.meta.vitest) {
const { it, expect } = import.meta.vitest;
it('add', () => {
expect(add()).toBe(0);
expect(add(1)).toBe(1);
expect(add(1, 2, 3)).toBe(6);
});
}
Erfahren Sie mehr unter In-Source-Testing.
Benchmarking Experimentell
Sie können Benchmark-Tests mit der Funktion bench
über Tinybench ausführen, um Leistungsvergleiche zu erhalten.
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;
});
});
});
Typ-Testing Experimentell
Sie können Tests schreiben, um Typ-Regressionen abzufangen. Vitest wird mit dem Paket expect-type
geliefert, um Ihnen eine ähnliche und leicht verständliche API bereitzustellen.
import { assertType, expectTypeOf, test } from 'vitest';
import { mount } from './mount.js';
test('my types work properly', () => {
expectTypeOf(mount).toBeFunction();
expectTypeOf(mount).parameter(0).toMatchTypeOf<{ name: string }>();
// @ts-expect-error name is a string
assertType(mount({ name: 42 }));
});
Sharding
Führen Sie Tests auf verschiedenen Maschinen mit den Flags --shard
und --reporter=blob
aus. Alle Test- und Abdeckungsergebnisse können am Ende Ihrer CI-Pipeline mit dem Befehl --merge-reports
zusammengeführt werden:
vitest --shard=1/2 --reporter=blob --coverage
vitest --shard=2/2 --reporter=blob --coverage
vitest --merge-reports --reporter=junit --coverage
Weitere Informationen finden Sie unter Improving Performance | Sharding
.
Umgebungsvariablen
Vitest lädt Umgebungsvariablen, die mit VITE_
beginnen, ausschließlich aus .env
-Dateien, um die Kompatibilität mit Frontend-bezogenen Tests zu gewährleisten und der etablierten Konvention von Vite zu folgen. Um dennoch alle Umgebungsvariablen aus .env
-Dateien zu laden, können Sie die Methode loadEnv
verwenden, die von vite
importiert wird:
import { loadEnv } from 'vite';
import { defineConfig } from 'vitest/config';
export default defineConfig(({ mode }) => ({
test: {
// mode definiert, welche ".env.{mode}"-Datei ausgewählt wird, falls vorhanden
env: loadEnv(mode, process.cwd(), ''),
},
}));
Unbehandelte Fehler
Standardmäßig fängt und meldet Vitest alle unhandled rejections, uncaught exceptions (in Node.js) und error-Ereignisse (im Browser).
Sie können dieses Verhalten deaktivieren, indem Sie die Fehler manuell abfangen. Vitest geht davon aus, dass der Callback
von Ihnen behandelt wird und meldet den Fehler nicht.
// in Node.js
process.on('unhandledRejection', () => {
// Ihr eigener Handler
});
process.on('uncaughtException', () => {
// Ihr eigener Handler
});
// im Browser
window.addEventListener('error', () => {
// Ihr eigener Handler
});
window.addEventListener('unhandledrejection', () => {
// Ihr eigener Handler
});
Alternativ können Sie gemeldete Fehler auch mit der Option dangerouslyIgnoreUnhandledErrors
ignorieren. Vitest wird sie weiterhin melden, aber sie werden das Testergebnis nicht beeinflussen (der Exit-Code wird sich nicht ändern).
Wenn Sie testen müssen, dass ein Fehler nicht abgefangen wurde, können Sie einen Test erstellen, der so aussieht:
test('my function throws uncaught error', async ({ onTestFinished }) => {
onTestFinished(() => {
// Wenn das Event während des Tests nie aufgerufen wurde,
// stellen Sie sicher, dass es vor dem nächsten Test entfernt wird
process.removeAllListeners('unhandledrejection');
});
return new Promise((resolve, reject) => {
process.once('unhandledrejection', error => {
try {
expect(error.message).toBe('my error');
resolve();
} catch (error) {
reject(error);
}
});
callMyFunctionThatRejectsError();
});
});