Skip to content
Vitest 3
Main Navigation Guide & APIConfigurationMode NavigateurAPI avancée
3.2.0
2.1.9
1.6.1
0.34.6

Français

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

Français

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

Apparence

Sidebar Navigation

Introduction

Pourquoi Vitest

Démarrage

Fonctionnalités

Configuration de Vitest

API

Référence de l'API des Tests

Fonctions Mocks

vi

expect

expectTypeOf

assert

assertType

Guide

Interface en ligne de commande (CLI)

Filtrage des tests

Projets de Test

Rapporteurs

Couverture de code

Instantanés

Simulation

Parallélisme

Tests de type

Interface utilisateur de Vitest

Tests in-source

Contexte de test

Annotations de test

Environnement de Test

Étendre les Matchers

Intégrations IDE

Débogage

Erreurs courantes

Guide de migration

Migration vers Vitest 3.0

Migration depuis Jest

Performance

Analyse des performances des tests

Amélioration des performances

Mode Navigateur

API avancée

Comparaison avec d'autres exécuteurs de tests

Sur cette page

Contexte de test ​

Inspiré des Playwright Fixtures, le contexte de test de Vitest vous permet de définir des utilitaires, des états internes et des fixtures qui peuvent être utilisés dans vos tests.

Utilisation ​

Le premier argument de chaque fonction de rappel de test est un contexte de test.

ts
import { it } from 'vitest';

it('should work', ({ task }) => {
  // affiche le nom du test en cours
  console.log(task.name);
});

Contexte de test intégré ​

task ​

Un objet en lecture seule contenant les métadonnées du test.

expect ​

L'API expect liée au test actuel :

ts
import { it } from 'vitest';

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

Cette API est utile pour exécuter des tests de snapshot en parallèle, car l'objet expect global ne peut pas les gérer correctement :

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;

Ignore l'exécution restante du test et le marque comme ignoré :

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

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

Depuis Vitest 3.1, cette fonction accepte un paramètre booléen pour ignorer le test conditionnellement :

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

Ajoute une annotation de test qui sera affichée par votre rapporteur.

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

signal 3.2.0+ ​

Un AbortSignal qui peut être annulé par Vitest. Le signal est annulé dans les situations suivantes :

  • Le test expire.
  • L'utilisateur a annulé manuellement l'exécution du test via Ctrl+C.
  • vitest.cancelCurrentRun a été appelé par programme.
  • Un autre test a échoué en parallèle et le drapeau bail est activé.
ts
it('stop request when test times out', async ({ signal }) => {
  await fetch('/resource', { signal });
}, 2000);

onTestFailed ​

Le hook onTestFailed lié au test actuel. Cette API est utile si vous exécutez des tests en parallèle et que vous avez besoin d'une gestion spécifique uniquement pour ce test.

onTestFinished ​

Le hook onTestFinished lié au test actuel. Cette API est utile si vous exécutez des tests en parallèle et que vous avez besoin d'une gestion spécifique uniquement pour ce test.

Étendre le contexte de test ​

Vitest propose deux méthodes différentes pour étendre le contexte de test.

test.extend ​

À l'instar de Playwright, vous pouvez utiliser cette méthode pour définir votre propre API test avec des fixtures personnalisées et la réutiliser n'importe où.

Par exemple, nous créons d'abord le collecteur test avec deux fixtures : todos et archive.

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

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

export const test = baseTest.extend({
  todos: async ({}, use) => {
    // initialise la fixture avant chaque test
    todos.push(1, 2, 3);

    // utilise la valeur de la fixture
    await use(todos);

    // nettoie la fixture après chaque test
    todos.length = 0;
  },
  archive,
});

Ensuite, nous pouvons l'importer et l'utiliser.

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

Nous pouvons également ajouter d'autres fixtures ou remplacer des fixtures existantes en étendant notre test.

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

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

Initialisation des fixtures ​

Le runner Vitest initialisera intelligemment vos fixtures et les injectera dans le contexte de test en fonction de leur utilisation.

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` ne s'exécutera pas
test('skip', () => {});
test('skip', ({ archive }) => {});

// `todos` s'exécutera
test('run', ({ todos }) => {});

WARNING

Lorsque vous utilisez test.extend() avec des fixtures, vous devez toujours utiliser le modèle de déstructuration d'objet { todos } pour accéder au contexte, à la fois dans la fonction de fixture et dans la fonction de test.

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

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

Fixture automatique ​

Vitest prend également en charge la syntaxe de tuple pour les fixtures, vous permettant de passer des options pour chaque fixture. Par exemple, vous pouvez l'utiliser pour initialiser explicitement une fixture, même si elle n'est pas utilisée dans les tests.

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

const test = base.extend({
  fixture: [
    async ({}, use) => {
      // cette fonction sera exécutée
      setup();
      await use();
      teardown();
    },
    { auto: true }, // Marque la fixture comme automatique
  ],
});

test('works correctly');

Fixture par défaut ​

Depuis Vitest 3, vous pouvez fournir différentes valeurs dans différents projets. Pour activer cette fonctionnalité, passez { injected: true } dans les options. Si la clé n'est pas spécifiée dans la configuration du projet, la valeur par défaut sera utilisée.

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

const test = base.extend({
  url: [
    // valeur par défaut si "url" n'est pas définie dans la configuration
    '/default',
    // marque la fixture comme "injectée" pour permettre la surcharge
    { injected: true },
  ],
});

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

Portée des valeurs par suite 3.1.0+ ​

Depuis Vitest 3.1, vous pouvez surcharger les valeurs de contexte par suite et ses enfants en utilisant l'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` utilise la nouvelle valeur surchargée qui a une portée limitée
    // à tous les tests de cette suite.
    expect(dependant).toEqual({ dependency: 'new' });
  });

  describe('keeps using scoped value', () => {
    test('uses scoped value', ({ dependant }) => {
      // la suite imbriquée a hérité de cette valeur
      expect(dependant).toEqual({ dependency: 'new' });
    });
  });
});

test('keep using the default values', ({ dependant }) => {
  // la `dependency` utilise la valeur par défaut
  // en dehors de la suite avec `.scoped`
  expect(dependant).toEqual({ dependency: 'default' });
});

Cette API est particulièrement utile si vous avez une valeur de contexte qui dépend d'une variable dynamique, comme une connexion à une base de données :

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

Contexte par portée 3.2.0+ ​

Vous pouvez définir un contexte qui sera initialisé une fois par fichier ou par worker. Il est initialisé de la même manière qu'une fixture régulière avec un paramètre d'objets :

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

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

La valeur est initialisée la première fois qu'un test y accède, à moins que les options de la fixture n'incluent auto: true – dans ce cas, la valeur est initialisée avant l'exécution de tout test.

ts
const test = baseTest.extend({
  perFile: [
    ({}, { use }) => use([]),
    {
      scope: 'file',
      // exécute toujours ce hook avant tout test
      auto: true,
    },
  ],
});

La portée worker exécutera la fixture une fois par worker. Le nombre de workers en cours d'exécution dépend de divers facteurs. Par défaut, chaque fichier s'exécute dans un worker distinct, de sorte que les portées file et worker fonctionnent de la même manière.

Cependant, si vous désactivez l'isolation, le nombre de workers est limité par la configuration maxWorkers ou poolOptions.

Notez que spécifier scope: 'worker' lors de l'exécution de tests dans vmThreads ou vmForks fonctionnera de la même manière que scope: 'file'. Cette limitation existe car chaque fichier de test a son propre contexte VM ; ainsi, si Vitest l'initialisait une seule fois, un contexte pourrait fuir vers un autre et créer de nombreuses incohérences de référence (par exemple, les instances de la même classe feraient référence à des constructeurs différents).

TypeScript ​

Pour fournir des types de fixture pour tous vos contextes personnalisés, vous pouvez passer le type des fixtures en tant que générique.

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

Inférence de type

Notez que Vitest ne prend pas en charge l'inférence des types lorsque la fonction use est appelée. Il est toujours préférable de passer le type de contexte entier en tant que type générique lors de l'appel à 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 et afterEach ​

Déprécié

C'est une méthode obsolète pour étendre le contexte et cela ne fonctionnera pas lorsque test est étendu avec test.extend.

Les contextes sont différents pour chaque test. Vous pouvez y accéder et les étendre via les hooks beforeEach et afterEach.

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

beforeEach(async context => {
  // étend le contexte
  context.foo = 'bar';
});

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

TypeScript ​

Pour fournir des types de propriété pour tous vos contextes personnalisés, vous pouvez augmenter le type TestContext en ajoutant :

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

Si vous souhaitez fournir des types de propriété uniquement pour des hooks beforeEach, afterEach, it et test spécifiques, vous pouvez passer le type en tant que générique.

ts
interface LocalTestContext {
  foo: string;
}

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

it<LocalTestContext>('should work', ({ foo }) => {
  // typeof foo est 'string'
  console.log(foo); // 'bar'
});
Pager
Page précédenteTests in-source
Page suivanteAnnotations de test

Publié sous la licence MIT.

Copyright (c) 2021-Present Vitest Team

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

Publié sous la licence MIT.

Copyright (c) 2021-Present Vitest Team