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

Einführung

Warum Vitest

Erste Schritte

Funktionen

Vitest konfigurieren

API

Test-API-Referenz

Mock-Funktionen

Vi

expect

expectTypeOf

assert

assertType

Leitfaden

Befehlszeilenschnittstelle

Testfilterung

Testprojekte

Reporter

Code-Abdeckung

Snapshot

Mocking

Parallelisierung

Typüberprüfungen

Vitest UI

Tests im Quellcode

Test-Kontext

Test-Annotationen

Testumgebung

Matcher erweitern

IDE-Integrationen

Debugging

Häufige Fehler

Migrationsleitfaden

Migration zu Vitest 3.0

Migration von Jest

Performance

Leistungsprofilierung von Tests

Leistung verbessern

Browser-Modus

Erweiterte API

Vergleiche mit anderen Test-Runnern

Auf dieser Seite

Test-Kontext ​

Inspiriert von Playwright Fixtures ermöglicht der Test-Kontext von Vitest die Definition von Hilfsfunktionen, Zuständen und Fixtures, die in Ihren Tests verwendet werden können.

Verwendung ​

Das erste Argument jedes Test-Callbacks ist ein Test-Kontext.

ts
import { it } from 'vitest';

it('should work', ({ task }) => {
  // Gibt den Namen des Tests aus
  console.log(task.name);
});

Eingebauter Test-Kontext ​

task ​

Ein schreibgeschütztes Objekt, das Metadaten über den Test enthält.

expect ​

Die expect-API ist an den aktuellen Test gebunden:

ts
import { it } from 'vitest';

it('math is easy', ({ expect }) => {
  expect(2 + 2).toBe(4);
});

Diese API ist nützlich für die parallele Ausführung von Snapshot-Tests, da das globale expect sie nicht verfolgen kann:

ts
import { it } from 'vitest';

it.concurrent('math is easy', ({ expect }) => {
  expect(2 + 2).toMatchInlineSnapshot();
});

it.concurrent('math is hard', ({ expect }) => {
  expect(2 * 2).toMatchInlineSnapshot();
});

skip ​

ts
function skip(note?: string): never;
function skip(condition: boolean, note?: string): void;

Überspringt die Ausführung nachfolgender Testschritte und markiert den Test als übersprungen:

ts
import { expect, it } from 'vitest';

it('math is hard', ({ skip }) => {
  skip();
  expect(2 + 2).toBe(5);
});

Seit Vitest 3.1 akzeptiert die Funktion einen booleschen Parameter, um den Test bedingt zu überspringen:

ts
it('math is hard', ({ skip, mind }) => {
  skip(mind === 'foggy');
  expect(2 + 2).toBe(5);
});

annotate 3.2.0+ ​

ts
function annotate(
  message: string,
  attachment?: TestAttachment
): Promise<TestAnnotation>;

function annotate(
  message: string,
  type?: string,
  attachment?: TestAttachment
): Promise<TestAnnotation>;

Fügt eine Test-Annotation hinzu, die in Ihrem Reporter angezeigt wird.

ts
test('annotations API', async ({ annotate }) => {
  await annotate('https://github.com/vitest-dev/vitest/pull/7953', 'issues');
});

signal 3.2.0+ ​

Ein AbortSignal, das von Vitest abgebrochen werden kann. Das Signal wird in folgenden Situationen abgebrochen:

  • Der Test überschreitet die Zeitvorgabe.
  • Der Benutzer hat den Testlauf manuell mit Strg+C abgebrochen.
  • vitest.cancelCurrentRun wurde programmgesteuert aufgerufen.
  • Ein anderer Test ist parallel fehlgeschlagen, und das bail-Flag ist gesetzt.
ts
it('stop request when test times out', async ({ signal }) => {
  await fetch('/resource', { signal });
}, 2000);

onTestFailed ​

Der onTestFailed-Hook ist an den aktuellen Test gebunden. Diese API ist nützlich, wenn Sie Tests gleichzeitig ausführen und eine spezielle Behandlung nur für diesen spezifischen Test benötigen.

onTestFinished ​

Der onTestFinished-Hook ist an den aktuellen Test gebunden. Diese API ist nützlich, wenn Sie Tests gleichzeitig ausführen und eine spezielle Behandlung nur für diesen spezifischen Test benötigen.

Test-Kontext erweitern ​

Vitest bietet zwei verschiedene Methoden zur Erweiterung des Test-Kontexts an.

test.extend ​

Ähnlich wie bei Playwright können Sie diese Methode nutzen, um Ihre eigene test-API mit benutzerdefinierten Fixtures zu definieren und überall wiederzuverwenden.

Zum Beispiel erstellen wir zuerst den test-Collector mit zwei Fixtures: todos und archive.

ts
import { test as baseTest } from 'vitest';

const todos = [];
const archive = [];

export const test = baseTest.extend({
  todos: async ({}, use) => {
    // Fixture vor jeder Testfunktion vorbereiten
    todos.push(1, 2, 3);

    // Fixture-Wert verwenden
    await use(todos);

    // Fixture nach jeder Testfunktion aufräumen
    todos.length = 0;
  },
  archive,
});

Anschließend können wir es importieren und verwenden.

ts
import { expect } from 'vitest';
import { test } from './my-test.js';

test('add items to todos', ({ todos }) => {
  expect(todos.length).toBe(3);

  todos.push(4);
  expect(todos.length).toBe(4);
});

test('move items from todos to archive', ({ todos, archive }) => {
  expect(todos.length).toBe(3);
  expect(archive.length).toBe(0);

  archive.push(todos.pop());
  expect(todos.length).toBe(2);
  expect(archive.length).toBe(1);
});

Zusätzlich können wir weitere Fixtures hinzufügen oder bestehende Fixtures überschreiben, indem wir unseren test erweitern.

ts
import { test as todosTest } from './my-test.js';

export const test = todosTest.extend({
  settings: {
    // ...
  },
});

Fixture-Initialisierung ​

Der Vitest-Runner initialisiert Ihre Fixtures bedarfsgerecht und injiziert sie basierend auf deren Verwendung in den Test-Kontext.

ts
import { test as baseTest } from 'vitest';

const test = baseTest.extend<{
  todos: number[];
  archive: number[];
}>({
  todos: async ({ task }, use) => {
    await use([1, 2, 3]);
  },
  archive: [],
});

// todos wird nicht ausgeführt
test('skip', () => {});
test('skip', ({ archive }) => {});

// todos wird ausgeführt
test('run', ({ todos }) => {});

WARNING

Wenn Sie test.extend() mit Fixtures verwenden, sollten Sie immer das Objekt-Destrukturierungs-Muster { todos } nutzen, um sowohl in der Fixture-Funktion als auch in der Testfunktion auf den Kontext zuzugreifen.

ts
test('context must be destructured', (context) => { 
  expect(context.todos.length).toBe(2)
})

test('context must be destructured', ({ todos }) => { 
  expect(todos.length).toBe(2)
})

Automatische Fixture ​

Vitest unterstützt auch die Tupel-Syntax für Fixtures, die es Ihnen ermöglicht, Optionen für jede Fixture zu übergeben. Zum Beispiel können Sie damit eine Fixture explizit initialisieren, auch wenn sie in Tests nicht verwendet wird.

ts
import { test as base } from 'vitest';

const test = base.extend({
  fixture: [
    async ({}, use) => {
      // dieser Hook wird ausgeführt
      setup();
      await use();
      teardown();
    },
    { auto: true }, // Als automatische Fixture markieren
  ],
});

test('works correctly');

Standard-Fixture ​

Seit Vitest 3 können Sie verschiedene Werte in verschiedenen Projekten bereitstellen. Um diese Funktion zu aktivieren, übergeben Sie { injected: true } an die Optionen. Wenn der Schlüssel in der Projektkonfiguration nicht angegeben ist, wird der Standardwert verwendet.

ts
import { test as base } from 'vitest';

const test = base.extend({
  url: [
    // Standardwert, wenn "url" in der Konfiguration nicht definiert ist
    '/default',
    // Fixture als "injected" markieren, um das Überschreiben zu ermöglichen
    { injected: true },
  ],
});

test('works correctly', ({ url }) => {
  // url ist "/default" in "project-new"
  // url ist "/full" in "project-full"
  // url ist "/empty" in "project-empty"
});
ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    projects: [
      {
        test: {
          name: 'project-new',
        },
      },
      {
        test: {
          name: 'project-full',
          provide: {
            url: '/full',
          },
        },
      },
      {
        test: {
          name: 'project-empty',
          provide: {
            url: '/empty',
          },
        },
      },
    ],
  },
});

Werte auf Suite beschränken 3.1.0+ ​

Seit Vitest 3.1 können Sie Kontextwerte pro Suite und deren Kindern überschreiben, indem Sie die test.scoped-API verwenden:

ts
import { test as baseTest, describe, expect } from 'vitest';

const test = baseTest.extend({
  dependency: 'default',
  dependant: ({ dependency }, use) => use({ dependency }),
});

describe('use scoped values', () => {
  test.scoped({ dependency: 'new' });

  test('uses scoped value', ({ dependant }) => {
    // `dependant` verwendet den neuen überschriebenen Wert, der auf alle Tests in dieser Suite beschränkt ist
    expect(dependant).toEqual({ dependency: 'new' });
  });

  describe('keeps using scoped value', () => {
    test('uses scoped value', ({ dependant }) => {
      // Geschachtelte Suite hat den Wert geerbt
      expect(dependant).toEqual({ dependency: 'new' });
    });
  });
});

test('keep using the default values', ({ dependant }) => {
  // Die `dependency` verwendet den Standardwert außerhalb der Suite, die mit `.scoped` definiert wurde
  expect(dependant).toEqual({ dependency: 'default' });
});

Diese API ist besonders nützlich, wenn Sie einen Kontextwert haben, der von einer dynamischen Variable wie einer Datenbankverbindung abhängt:

ts
const test = baseTest.extend<{
  db: Database;
  schema: string;
}>({
  db: async ({ schema }, use) => {
    const db = await createDb({ schema });
    await use(db);
    await cleanup(db);
  },
  schema: '',
});

describe('one type of schema', () => {
  test.scoped({ schema: 'schema-1' });

  // ... Tests
});

describe('another type of schema', () => {
  test.scoped({ schema: 'schema-2' });

  // ... Tests
});

Kontext pro Geltungsbereich 3.2.0+ ​

Sie können einen Kontext definieren, der einmal pro Datei oder Worker initialisiert wird. Er wird auf die gleiche Weise wie eine reguläre Fixture mit einem Objekt als Parameter initialisiert:

ts
import { test as baseTest } from 'vitest';

export const test = baseTest.extend({
  perFile: [({}, { use }) => use([]), { scope: 'file' }],
  perWorker: [({}, { use }) => use([]), { scope: 'worker' }],
});

Der Wert wird initialisiert, sobald ein Test darauf zugreift. Eine Ausnahme bildet der Fall, wenn die Fixture-Optionen auto: true enthalten – dann wird der Wert initialisiert, bevor ein Test ausgeführt wird.

ts
const test = baseTest.extend({
  perFile: [
    ({}, { use }) => use([]),
    {
      scope: 'file',
      // diesen Hook immer vor jedem Test ausführen
      auto: true,
    },
  ],
});

Der worker-Geltungsbereich führt die Fixture einmal pro Worker aus. Die Anzahl der laufenden Worker hängt von verschiedenen Faktoren ab. Standardmäßig läuft jede Datei in einem separaten Worker, sodass die Geltungsbereiche file und worker auf die gleiche Weise funktionieren.

Wenn Sie jedoch die Isolation deaktivieren, wird die Anzahl der Worker durch die Konfiguration von maxWorkers oder poolOptions begrenzt.

Beachten Sie, dass die Angabe von scope: 'worker' beim Ausführen von Tests in vmThreads oder vmForks auf die gleiche Weise funktioniert wie scope: 'file'. Diese Einschränkung besteht, weil jede Testdatei ihren eigenen VM-Kontext hat. Wenn Vitest sie einmal initialisieren würde, könnte ein Kontext in einen anderen durchsickern und viele Referenzinkonsistenzen verursachen (Instanzen derselben Klasse würden beispielsweise auf verschiedene Konstruktoren verweisen).

TypeScript ​

Um Fixture-Typen für alle Ihre benutzerdefinierten Kontexte bereitzustellen, können Sie den Fixture-Typ als generischen Typ übergeben.

ts
interface MyFixtures {
  todos: number[];
  archive: number[];
}

const test = baseTest.extend<MyFixtures>({
  todos: [],
  archive: [],
});

test('types are defined correctly', ({ todos, archive }) => {
  expectTypeOf(todos).toEqualTypeOf<number[]>();
  expectTypeOf(archive).toEqualTypeOf<number[]>();
});

Typinferenz

Beachten Sie, dass Vitest die Typen nicht ableiten kann, wenn die use-Funktion aufgerufen wird. Es ist immer empfehlenswert, den gesamten Kontexttyp als generischen Typ zu übergeben, wenn test.extend aufgerufen wird:

ts
import { test as baseTest } from 'vitest';

const test = baseTest.extend<{
  todos: number[];
  schema: string;
}>({
  todos: ({ schema }, use) => use([]),
  schema: 'test',
});

test('types are correct', ({
  todos, // number[]
  schema, // string
}) => {
  // ...
});

beforeEach und afterEach ​

Veraltet

Dies ist eine veraltete Methode zur Kontext-Erweiterung und funktioniert nicht, wenn der test mit test.extend erweitert wird.

Die Kontexte sind für jeden Test unterschiedlich. Sie können sie innerhalb der beforeEach- und afterEach-Hooks aufrufen und erweitern.

ts
import { beforeEach, it } from 'vitest';

beforeEach(async context => {
  // Kontext erweitern
  context.foo = 'bar';
});

it('should work', ({ foo }) => {
  console.log(foo); // 'bar'
});

TypeScript ​

Um Eigenschaftstypen für alle Ihre benutzerdefinierten Kontexte bereitzustellen, können Sie den Typ TestContext erweitern, indem Sie Folgendes hinzufügen:

ts
declare module 'vitest' {
  export interface TestContext {
    foo?: string;
  }
}

Wenn Sie Eigenschaftstypen nur für bestimmte beforeEach-, afterEach-, it- und test-Hooks bereitstellen möchten, können Sie den Typ als generischen Typ übergeben.

ts
interface LocalTestContext {
  foo: string;
}

beforeEach<LocalTestContext>(async context => {
  // typeof context ist 'TestContext & LocalTestContext'
  context.foo = 'bar';
});

it<LocalTestContext>('should work', ({ foo }) => {
  // typeof foo ist 'string'
  console.log(foo); // 'bar'
});
Pager
Vorherige SeiteTests im Quellcode
Nächste SeiteTest-Annotationen

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/guide/test-context

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2021-Present Vitest Team