Skip to content
Vitest 3
Main Navigation Leitfaden & APIKonfigurationBrowser-ModusFortgeschritten API
3.2.0
2.1.9
1.6.1
0.34.6

Deutsch

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Deutsch

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Aussehen

Sidebar Navigation

API

Node API

Erweiterte API

Vitest API

TestProject

TestSpecification

Test Task API

TestCase

TestSuite

TestModule

TestCollection

Plugin-API

Runner API

Reporter

Aufgaben-Metadaten

Leitfaden

Tests ausführen

Reporter erweitern

Benutzerdefinierter Pool

Vitest konfigurieren

Test-API-Referenz

Auf dieser Seite

Runner API ​

WARNING

Dies ist eine fortgeschrittene API. Wenn Sie lediglich Tests ausführen möchten, benötigen Sie diese wahrscheinlich nicht. Sie wird hauptsächlich von Bibliotheksautoren verwendet.

Sie können den Pfad zu Ihrem Test-Runner mit der Option runner in Ihrer Konfigurationsdatei angeben. Diese Datei sollte einen Standardexport mit einem Klassenkonstruktor enthalten, der die folgende Schnittstelle implementiert:

ts
export interface VitestRunner {
  /**
   * Wird als Erstes aufgerufen, bevor Tests tatsächlich gesammelt und ausgeführt werden.
   */
  onBeforeCollect?: (paths: string[]) => unknown;
  /**
   * Wird nach dem Sammeln von Tests und vor "onBeforeRun" aufgerufen.
   */
  onCollected?: (files: File[]) => unknown;

  /**
   * Wird aufgerufen, wenn der Test-Runner die nächsten Testläufe abbrechen soll.
   * Der Runner sollte diese Methode überwachen und Tests sowie Suiten in
   * "onBeforeRunSuite" und "onBeforeRunTask" als übersprungen markieren, sobald sie aufgerufen wird.
   */
  onCancel?: (reason: CancelReason) => unknown;

  /**
   * Wird vor dem Ausführen eines einzelnen Tests aufgerufen. Enthält noch kein 'result'.
   */
  onBeforeRunTask?: (test: TaskPopulated) => unknown;
  /**
   * Wird vor dem eigentlichen Ausführen der Testfunktion aufgerufen. Verfügt bereits über 'result' mit 'state' und 'startTime'.
   */
  onBeforeTryTask?: (
    test: TaskPopulated,
    options: { retry: number; repeats: number }
  ) => unknown;
  /**
   * Wird aufgerufen, nachdem das Ergebnis und der Status festgelegt wurden.
   */
  onAfterRunTask?: (test: TaskPopulated) => unknown;
  /**
   * Wird direkt nach dem Ausführen der Testfunktion aufgerufen. Der neue Status steht noch nicht fest. Wird nicht aufgerufen, falls die Testfunktion einen Fehler auslöst.
   */
  onAfterTryTask?: (
    test: TaskPopulated,
    options: { retry: number; repeats: number }
  ) => unknown;

  /**
   * Wird vor dem Ausführen einer einzelnen Suite aufgerufen. Enthält noch kein 'result'.
   */
  onBeforeRunSuite?: (suite: Suite) => unknown;
  /**
   * Wird nach dem Ausführen einer einzelnen Suite aufgerufen. Hat Status und Ergebnis.
   */
  onAfterRunSuite?: (suite: Suite) => unknown;

  /**
   * Wenn definiert, wird diese Methode anstelle der üblichen Vitest-Suite-Partitionierung und -Behandlung aufgerufen.
   * "before"- und "after"-Hooks werden nicht ignoriert.
   */
  runSuite?: (suite: Suite) => Promise<void>;
  /**
   * Wenn definiert, wird diese Methode anstelle der üblichen Vitest-Behandlung aufgerufen. Dies ist nützlich, wenn Sie Ihre eigene Testfunktion haben.
   * "before"- und "after"-Hooks werden nicht ignoriert.
   */
  runTask?: (test: TaskPopulated) => Promise<void>;

  /**
   * Wird aufgerufen, wenn eine Aufgabe aktualisiert wird. Dasselbe wie "onTaskUpdate" in einem Reporter, jedoch läuft dies im selben Thread wie die Tests.
   */
  onTaskUpdate?: (
    task: [string, TaskResult | undefined, TaskMeta | undefined][]
  ) => Promise<void>;

  /**
   * Wird vor dem Ausführen aller Tests in gesammelten Pfaden aufgerufen.
   */
  onBeforeRunFiles?: (files: File[]) => unknown;
  /**
   * Wird direkt nach dem Ausführen aller Tests in gesammelten Pfaden aufgerufen.
   */
  onAfterRunFiles?: (files: File[]) => unknown;
  /**
   * Wird aufgerufen, wenn ein neuer Kontext für einen Test definiert wird. Dies ist nützlich, wenn Sie dem Kontext benutzerdefinierte Eigenschaften hinzufügen möchten.
   * Wenn Sie lediglich einen benutzerdefinierten Kontext mit einem Runner definieren möchten, sollten Sie stattdessen "beforeAll" in "setupFiles" verwenden.
   */
  extendTaskContext?: (context: TestContext) => TestContext;
  /**
   * Wird aufgerufen, wenn bestimmte Dateien importiert werden. Kann in zwei Situationen aufgerufen werden: zum Sammeln von Tests und zum Importieren von Setup-Dateien.
   */
  importFile: (filepath: string, source: VitestRunnerImportSource) => unknown;
  /**
   * Funktion, die aufgerufen wird, wenn der Runner versucht, den Wert zu erhalten, sobald `test.extend` mit `{ injected: true }` verwendet wird.
   */
  injectValue?: (key: string) => unknown;
  /**
   * Öffentlich zugängliche Konfiguration.
   */
  config: VitestRunnerConfig;
  /**
   * Der Name des aktuellen Pools. Beeinflusst möglicherweise, wie der Stack-Trace auf der Serverseite ermittelt wird.
   */
  pool?: string;
}

Beim Instanziieren dieser Klasse übergibt Vitest die Vitest-Konfiguration, die Sie als config-Eigenschaft verfügbar machen sollten:

ts
import type { RunnerTestFile } from 'vitest';
import type { VitestRunner, VitestRunnerConfig } from 'vitest/suite';
import { VitestTestRunner } from 'vitest/runners';

class CustomRunner extends VitestTestRunner implements VitestRunner {
  public config: VitestRunnerConfig;

  constructor(config: VitestRunnerConfig) {
    this.config = config;
  }

  onAfterRunFiles(files: RunnerTestFile[]) {
    console.log('finished running', files);
  }
}

export default CustomRunner;

WARNING

Vitest injiziert auch eine Instanz von ViteNodeRunner als Eigenschaft __vitest_executor. Sie können diese verwenden, um Dateien in der Methode importFile zu verarbeiten (dies ist das Standardverhalten von TestRunner und BenchmarkRunner).

ViteNodeRunner stellt die Methode executeId zur Verfügung, die verwendet wird, um Testdateien in einer Vite-freundlichen Umgebung zu importieren. Das bedeutet, sie löst Importe auf und transformiert den Dateiinhalt zur Laufzeit, damit Node.js ihn verstehen kann:

ts
export default class Runner {
  async importFile(filepath: string) {
    await this.__vitest_executor.executeId(filepath);
  }
}

WARNING

Wenn Sie keinen benutzerdefinierten Runner haben oder die Methode runTask nicht definiert haben, versucht Vitest, eine Aufgabe automatisch abzurufen. Wenn Sie keine Funktion mit setFn hinzugefügt haben, wird dies fehlschlagen.

TIP

Snapshot-Unterstützung und einige andere Funktionen hängen vom Runner ab. Wenn Sie diese nicht verlieren möchten, können Sie Ihren Runner von VitestTestRunner erweitern, das von vitest/runners importiert wird. Es stellt auch BenchmarkNodeRunner zur Verfügung, wenn Sie die Benchmark-Funktionalität erweitern möchten.

Aufgaben ​

WARNING

Die "Runner Tasks API" ist experimentell und sollte primär nur in der Testlaufzeit verwendet werden. Vitest stellt auch die "Reported Tasks API" zur Verfügung, die bevorzugt werden sollte, wenn im Hauptthread (z.B. innerhalb des Reporters) gearbeitet wird.

Das Team diskutiert derzeit, ob "Runner Tasks" zukünftig durch "Reported Tasks" ersetzt werden sollen.

Suiten und Tests werden intern als Aufgaben bezeichnet. Der Vitest-Runner initialisiert eine File-Aufgabe, bevor er Tests sammelt – dies ist eine erweiterte Version von Suite mit einigen zusätzlichen Eigenschaften. Diese ist für jede Aufgabe (einschließlich File) als file-Eigenschaft verfügbar.

ts
interface File extends Suite {
  /**
   * Der Name des Pools, zu dem die Datei gehört.
   * @default 'forks'
   */
  pool?: string;
  /**
   * Der Pfad zur Datei im UNIX-Format.
   */
  filepath: string;
  /**
   * Der Name des Testprojekts, zu dem die Datei gehört.
   */
  projectName: string | undefined;
  /**
   * Die Zeit, die zum Sammeln aller Tests in der Datei benötigt wurde.
   * Diese Zeit beinhaltet auch das Importieren aller Dateiabhängigkeiten.
   */
  collectDuration?: number;
  /**
   * Die Zeit, die zum Importieren der Setup-Datei benötigt wurde.
   */
  setupDuration?: number;
}

Jede Suite hat eine tasks-Eigenschaft, die während der Sammelphase gefüllt wird. Dies ist nützlich, um den Aufgabenbaum von oben nach unten zu traversieren.

ts
interface Suite extends TaskBase {
  type: 'suite';
  /**
   * Datei-Aufgabe. Es ist die Wurzelaufgabe der Datei.
   */
  file: File;
  /**
   * Ein Array von Aufgaben, die Teil der Suite sind.
   */
  tasks: Task[];
}

Jede Aufgabe hat eine suite-Eigenschaft, die auf die Suite verweist, in der sie sich befindet. Wenn test oder describe auf der obersten Ebene initialisiert werden, besitzen sie keine suite-Eigenschaft (sie wird nicht gleich file sein!). File hat auch niemals eine suite-Eigenschaft. Dies ist nützlich, um die Aufgaben von unten nach oben zu traversieren.

ts
interface Test<ExtraContext = object> extends TaskBase {
  type: 'test';
  /**
   * Testkontext, der an die Testfunktion übergeben wird.
   */
  context: TestContext & ExtraContext;
  /**
   * Datei-Aufgabe. Es ist die Wurzelaufgabe der Datei.
   */
  file: File;
  /**
   * Ob die Aufgabe durch Aufruf von `context.skip()` übersprungen wurde.
   */
  pending?: boolean;
  /**
   * Ob die Aufgabe erfolgreich sein sollte, wenn sie fehlschlägt. Wenn die Aufgabe fehlschlägt, wird sie als bestanden markiert.
   */
  fails?: boolean;
  /**
   * Speichert Promises (von async expects), um auf sie zu warten, bevor der Test beendet wird.
   */
  promises?: Promise<any>[];
}

Jede Aufgabe kann ein result-Feld haben. Suiten können dieses Feld nur haben, wenn ein Fehler, der innerhalb eines Suite-Callbacks oder der beforeAll-/afterAll-Callbacks auftritt, sie daran hindert, Tests zu sammeln. Tests haben dieses Feld immer, nachdem ihre Rückruffunktionen aufgerufen wurden – die Felder state und errors sind je nach Ergebnis vorhanden. Wenn ein Fehler in beforeEach oder afterEach-Rückruffunktionen ausgelöst wurde, ist der entsprechende Fehler in task.result.errors vorhanden.

ts
export interface TaskResult {
  /**
   * Status der Aufgabe. Erbt den `task.mode` während der Sammlung.
   * Nach Abschluss der Aufgabe wird er auf `pass` oder `fail` geändert.
   * - **pass**: Aufgabe wurde erfolgreich durchgeführt
   * - **fail**: Aufgabe fehlgeschlagen
   */
  state: TaskState;
  /**
   * Fehler, die während der Aufgabenausführung aufgetreten sind. Es ist möglich, mehrere Fehler zu haben,
   * wenn `expect.soft()` mehrfach fehlgeschlagen ist.
   */
  errors?: ErrorWithDiff[];
  /**
   * Die Ausführungsdauer der Aufgabe in Millisekunden.
   */
  duration?: number;
  /**
   * Zeitstempel in Millisekunden, zu dem die Aufgabe gestartet wurde.
   */
  startTime?: number;
  /**
   * Speicherverbrauch in Bytes nach Beendigung der Aufgabe.
   * Nur verfügbar, wenn die Option `logHeapUsage` gesetzt ist und `process.memoryUsage` definiert ist.
   */
  heap?: number;
  /**
   * Status der mit dieser Aufgabe verbundenen Hooks. Für Berichtszwecke nützlich.
   */
  hooks?: Partial<
    Record<'afterAll' | 'beforeAll' | 'beforeEach' | 'afterEach', TaskState>
  >;
  /**
   * Die Anzahl der Wiederholungsversuche der Aufgabe. Die Aufgabe wird nur wiederholt, wenn sie
   * fehlgeschlagen ist und die Option `retry` gesetzt ist.
   */
  retryCount?: number;
  /**
   * Die Anzahl der Wiederholungen der Aufgabe. Die Aufgabe wird nur wiederholt, wenn
   * die Option `repeats` gesetzt ist. Dieser Wert beinhaltet ebenfalls `retryCount`.
   */
  repeatCount?: number;
}

Ihre Aufgabenfunktion ​

Vitest stellt die Hilfsfunktion createTaskCollector zur Verfügung, um Ihre eigene test-Methode zu erstellen. Sie verhält sich wie ein Test, ruft aber während der Sammlung eine benutzerdefinierte Methode auf.

Eine Aufgabe ist ein Objekt, das Teil einer Suite ist. Es wird automatisch der aktuellen Suite über die Methode suite.task hinzugefügt:

js
import { createTaskCollector, getCurrentSuite } from 'vitest/suite';

export { afterAll, beforeAll, describe } from 'vitest';

// Diese Funktion wird während der Sammelphase aufgerufen:
// Rufen Sie hier keinen Funktionshandler auf, sondern fügen Sie ihn zu den Suite-Aufgaben hinzu
// mit der Methode "getCurrentSuite().task()"
// Hinweis: createTaskCollector unterstützt "todo"/"each"/...
export const myCustomTask = createTaskCollector(function (name, fn, timeout) {
  getCurrentSuite().task(name, {
    ...this, // damit "todo"/"skip"/... korrekt erfasst wird
    meta: {
      customPropertyToDifferentiateTask: true,
    },
    handler: fn,
    timeout,
  });
});
js
import { afterAll, beforeAll, describe, myCustomTask } from './custom.js';
import { gardener } from './gardener.js';

describe('take care of the garden', () => {
  beforeAll(() => {
    gardener.putWorkingClothes();
  });

  myCustomTask('weed the grass', () => {
    gardener.weedTheGrass();
  });
  myCustomTask.todo('mow the lawn', () => {
    gardener.mowerTheLawn();
  });
  myCustomTask('water flowers', () => {
    gardener.waterFlowers();
  });

  afterAll(() => {
    gardener.goHome();
  });
});
bash
vitest ./garden/tasks.test.js
Pager
Vorherige SeitePlugin-API
Nächste SeiteReporter

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/advanced/runner

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2021-Present Vitest Team