Skip to content
Vitest 3
Main Navigation Przewodnik & APIKonfiguracjaTryb przeglądarkiZaawansowane API
3.2.0
2.1.9
1.6.1
0.34.6

Polski

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

Polski

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

Wygląd

Sidebar Navigation

Wprowadzenie

Dlaczego Vitest

Pierwsze kroki

Funkcje

Konfiguracja Vitest

API

Dokumentacja API testowego

Funkcje Mock

Vi

expect

expectTypeOf

assert

assertType

Przewodnik

Interfejs Wiersza Poleceń

Filtrowanie testów

Projekty testowe

Reportery

Pokrycie kodu

Migawki

Mockowanie

Równoległość

Typy testów

Interfejs użytkownika Vitest

Testy w kodzie źródłowym

Kontekst Testu

Adnotacje testowe

Środowisko testowe

Rozszerzanie matcherów

Integracje z IDE

Debugowanie

Typowe błędy

Przewodnik migracji

Migracja do Vitest 3.0

Migracja z Jest

Wydajność

Profilowanie wydajności testów

Poprawa wydajności

Tryb przeglądarkowy

Zaawansowane API

Porównania z innymi narzędziami do uruchamiania testów

Na tej stronie

Kontekst Testu ​

Zainspirowany przez Playwright Fixtures, kontekst testowy Vitest umożliwia definiowanie narzędzi, stanów i tzw. "fixtures", które mogą być wykorzystywane w testach.

Użycie ​

Pierwszym argumentem każdej funkcji zwrotnej testu jest kontekst testu.

ts
import { it } from 'vitest';

it('should work', ({ task }) => {
  // wyświetla nazwę testu
  console.log(task.name);
});

Wbudowany Kontekst Testu ​

task ​

Obiekt tylko do odczytu, zawierający metadane dotyczące testu.

expect ​

API expect, które jest powiązane z bieżącym testem:

ts
import { it } from 'vitest';

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

To API jest przydatne do równoległego uruchamiania testów snapshotowych, ponieważ globalny obiekt expect nie może ich monitorować:

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;

Pomija dalsze wykonanie testu i oznacza go jako pominięty:

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

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

Od Vitest 3.1 akceptuje parametr typu boolean, aby warunkowo pominąć test:

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>;

Dodaje adnotację testową, która zostanie wyświetlona przez reporter.

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

signal 3.2.0+ ​

AbortSignal, który może zostać przerwany przez Vitest. Sygnał jest anulowany w następujących sytuacjach:

  • Upływa limit czasu testu
  • Użytkownik ręcznie anulował test za pomocą Ctrl+C
  • vitest.cancelCurrentRun zostało wywołane programowo
  • Inny test zakończył się równolegle niepowodzeniem i flaga bail jest ustawiona
ts
it('stop request when test times out', async ({ signal }) => {
  await fetch('/resource', { signal });
}, 2000);

onTestFailed ​

Hook onTestFailed powiązany z bieżącym testem. To API jest przydatne, gdy uruchamiasz testy równolegle i potrzebujesz specjalnego traktowania tylko dla tego konkretnego testu.

onTestFinished ​

Hook onTestFinished powiązany z bieżącym testem. To API jest przydatne, gdy uruchamiasz testy równolegle i potrzebujesz specjalnego traktowania tylko dla tego konkretnego testu.

Rozszerzanie Kontekstu Testu ​

Vitest zapewnia dwa różne sposoby rozszerzania kontekstu testu.

test.extend ​

Analogicznie do Playwright, możesz użyć tej metody do zdefiniowania własnego API test z niestandardowymi "fixtures" i ponownego użycia go w dowolnym miejscu.

Na przykład, najpierw definiujemy API test z dwoma "fixtures": todos i archive.

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

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

export const test = baseTest.extend({
  todos: async ({}, use) => {
    // konfiguracja fixture przed każdym testem
    todos.push(1, 2, 3);

    // użycie wartości fixture
    await use(todos);

    // czyszczenie fixture po każdym teście
    todos.length = 0;
  },
  archive,
});

Następnie możemy go zaimportować i użyć.

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);
});

Możemy również dodać więcej "fixtures" lub nadpisać istniejące "fixtures" poprzez rozszerzenie naszego test.

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

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

Inicjalizacja Fixture ​

Moduł uruchamiający Vitest inteligentnie zainicjuje "fixtures" i wstrzyknie je do kontekstu testu w oparciu o ich użycie.

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 nie zostanie uruchomione
test('skip', () => {});
test('skip', ({ archive }) => {});

// todos zostanie uruchomione
test('run', ({ todos }) => {});

WARNING

Podczas używania test.extend() z "fixtures", zawsze należy używać wzorca dekonstrukcji obiektu { todos } do dostępu do kontekstu zarówno w funkcji "fixture", jak i w funkcji testu.

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

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

Automatyczna Fixture ​

Vitest obsługuje również składnię tupli dla "fixtures", pozwalając na przekazywanie opcji dla każdej "fixture". Na przykład, możesz jej użyć do jawnego inicjowania "fixture", nawet jeśli nie jest ona używana w testach.

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

const test = base.extend({
  fixture: [
    async ({}, use) => {
      // ta funkcja zostanie uruchomiona
      setup();
      await use();
      teardown();
    },
    { auto: true }, // Oznacz jako automatyczną fixture
  ],
});

test('works correctly');

Domyślna Fixture ​

Od Vitest 3, możesz zapewnić różne wartości w różnych projektach. Aby włączyć tę funkcję, przekaż { injected: true } w opcjach. Jeśli klucz nie jest określony w konfiguracji projektu, zostanie użyta wartość domyślna.

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

const test = base.extend({
  url: [
    // wartość domyślna, jeśli "url" nie zostało zdefiniowane w konfiguracji
    '/default',
    // oznacz fixture jako injected, aby umożliwić nadpisanie
    { injected: true },
  ],
});

test('works correctly', ({ url }) => {
  // url to "/default" w "project-new"
  // url to "/full" w "project-full"
  // url to "/empty" w "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',
          },
        },
      },
    ],
  },
});

Zakres Wartości dla Suite 3.1.0+ ​

Od Vitest 3.1, możesz nadpisywać wartości kontekstu dla każdego zestawu testów (suite) i jego dzieci, używając API test.scoped:

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` używa nowej nadpisanej wartości, która dotyczy
    // wszystkich testów w tym suite
    expect(dependant).toEqual({ dependency: 'new' });
  });

  describe('keeps using scoped value', () => {
    test('uses scoped value', ({ dependant }) => {
      // zagnieżdżony suite odziedziczył wartość
      expect(dependant).toEqual({ dependency: 'new' });
    });
  });
});

test('keep using the default values', ({ dependant }) => {
  // `dependency` używa wartości domyślnej
  // poza suite z .scoped
  expect(dependant).toEqual({ dependency: 'default' });
});

To API jest szczególnie przydatne, jeśli masz wartość kontekstu, która zależy od zmiennej dynamicznej, takiej jak połączenie z bazą danych:

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' });

  // ... testy
});

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

  // ... testy
});

Kontekst dla poszczególnych zakresów 3.2.0+ ​

Możesz zdefiniować kontekst, który zostanie zainicjowany raz na plik lub na worker. Jest on inicjowany w ten sam sposób, co zwykła "fixture", przyjmując obiekt jako parametr:

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

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

Wartość jest inicjowana za pierwszym razem, gdy jakikolwiek test ma do niej dostęp, chyba że opcje "fixture" mają auto: true - w tym przypadku wartość jest inicjowana przed uruchomieniem jakiegokolwiek testu.

ts
const test = baseTest.extend({
  perFile: [
    ({}, { use }) => use([]),
    {
      scope: 'file',
      // zawsze uruchamiany ten hook przed jakimkolwiek testem
      auto: true,
    },
  ],
});

Zakres worker uruchomi "fixture" raz na worker. Liczba uruchomionych workerów zależy od różnych czynników. Domyślnie każdy plik działa w osobnym workerze, więc zakresy file i worker działają tak samo.

Jednakże, jeśli izolacja zostanie wyłączona (izolację), to liczba workerów jest ograniczona przez konfigurację maxWorkers lub poolOptions.

Zauważ, że określenie scope: 'worker' podczas uruchamiania testów w vmThreads lub vmForks będzie działać tak samo jak scope: 'file'. To ograniczenie istnieje, ponieważ każdy plik testowy ma swój własny kontekst VM, więc gdyby Vitest zainicjował go jednokrotnie, jeden kontekst mógłby przeniknąć do drugiego i stworzyć wiele niespójności referencyjnych (instancje tej samej klasy odwoływałyby się do różnych konstruktorów, na przykład).

TypeScript ​

Aby zapewnić typy "fixture" dla wszystkich niestandardowych kontekstów, możesz przekazać typ "fixtures" jako typ generyczny.

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[]>();
});

Wnioskowanie typów

Zauważ, że Vitest nie obsługuje wnioskowania typów, gdy wywoływana jest funkcja use. Zawsze preferowane jest przekazywanie całego typu kontekstu jako typu generycznego, gdy wywoływana jest test.extend:

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 i afterEach ​

Przestarzałe

To przestarzały sposób rozszerzania kontekstu i nie będzie działać, gdy test zostanie rozszerzony za pomocą test.extend.

Konteksty są różne dla każdego testu. Można uzyskać do nich dostęp i rozszerzyć je w hookach beforeEach i afterEach.

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

beforeEach(async context => {
  // rozszerz kontekst
  context.foo = 'bar';
});

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

TypeScript ​

Aby zapewnić typy właściwości dla wszystkich niestandardowych kontekstów, można rozszerzyć typ TestContext dodając:

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

Jeśli typy właściwości mają być zapewnione tylko dla konkretnych hooków beforeEach, afterEach, it i test, można przekazać typ jako typ generyczny.

ts
interface LocalTestContext {
  foo: string;
}

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

it<LocalTestContext>('should work', ({ foo }) => {
  // typeof foo to 'string'
  console.log(foo); // 'bar'
});
Pager
Poprzednia stronaTesty w kodzie źródłowym
Następna stronaAdnotacje testowe

Opublikowano na licencji MIT.

Copyright (c) 2021-Present Vitest Team

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

Opublikowano na licencji MIT.

Copyright (c) 2021-Present Vitest Team