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

API

Node API

API avancée

API Vitest

TestProject

TestSpecification

Test Task API

TestCase

TestSuite

TestModule

TestCollection

API des plugins

API du Runner

Rapporteurs

Métadonnées de tâche

Guide

Exécuter les tests

Extension des Rapporteurs

Pool personnalisé

Configuration de Vitest

Référence de l'API des Tests

Sur cette page

API du Runner ​

WARNING

C'est une API avancée. Si vous souhaitez simplement exécuter des tests, vous n'en aurez probablement pas besoin. Elle est principalement destinée aux auteurs de bibliothèques.

Vous pouvez spécifier le chemin vers votre runner de test via l'option runner dans votre fichier de configuration. Ce fichier doit exporter par défaut une classe implémentant les méthodes suivantes :

ts
export interface VitestRunner {
  /**
   * Première méthode appelée avant la collecte et l'exécution des tests.
   */
  onBeforeCollect?: (paths: string[]) => unknown;
  /**
   * Appelé après la collecte des tests et avant "onBeforeRun".
   */
  onCollected?: (files: File[]) => unknown;

  /**
   * Appelé lorsque le *runner* de test doit annuler les exécutions de tests à venir.
   * Le *runner* doit surveiller cette méthode et marquer les tests et les suites comme ignorés dans
   * "onBeforeRunSuite" et "onBeforeRunTask" lorsqu'elle est invoquée.
   */
  onCancel?: (reason: CancelReason) => unknown;

  /**
   * Appelé avant l'exécution d'une tâche de test individuelle. Le champ "result" n'est pas encore disponible.
   */
  onBeforeRunTask?: (test: TaskPopulated) => unknown;
  /**
   * Appelé avant l'exécution de la fonction de test. Le champ "result" est déjà renseigné avec "state" et "startTime".
   */
  onBeforeTryTask?: (
    test: TaskPopulated,
    options: { retry: number; repeats: number }
  ) => unknown;
  /**
   * Appelé une fois que le résultat et l'état sont définis.
   */
  onAfterRunTask?: (test: TaskPopulated) => unknown;
  /**
   * Appelé juste après l'exécution de la fonction de test. Le nouvel état n'est pas encore disponible. Cette méthode ne sera pas appelée si la fonction de test lève une exception.
   */
  onAfterTryTask?: (
    test: TaskPopulated,
    options: { retry: number; repeats: number }
  ) => unknown;

  /**
   * Appelé avant l'exécution d'une suite individuelle. Le champ "result" n'est pas encore disponible.
   */
  onBeforeRunSuite?: (suite: Suite) => unknown;
  /**
   * Appelé après l'exécution d'une suite individuelle. L'état et le résultat sont disponibles.
   */
  onAfterRunSuite?: (suite: Suite) => unknown;

  /**
   * Si définie, cette méthode sera appelée à la place de la gestion et de la répartition habituelles des suites Vitest.
   * Les hooks "before" et "after" ne seront pas ignorés.
   */
  runSuite?: (suite: Suite) => Promise<void>;
  /**
   * Si définie, cette méthode sera appelée à la place de la gestion habituelle de Vitest. C'est utile si vous disposez de votre propre fonction de test personnalisée.
   * Les hooks "before" et "after" ne seront pas ignorés.
   */
  runTask?: (test: TaskPopulated) => Promise<void>;

  /**
   * Appelé lorsqu'une tâche est mise à jour. Identique à "onTaskUpdate" dans un rapporteur, mais s'exécute dans le même thread que les tests.
   */
  onTaskUpdate?: (
    task: [string, TaskResult | undefined, TaskMeta | undefined][]
  ) => Promise<void>;

  /**
   * Appelé avant l'exécution de tous les tests dans les chemins collectés.
   */
  onBeforeRunFiles?: (files: File[]) => unknown;
  /**
   * Appelé juste après l'exécution de tous les tests dans les chemins collectés.
   */
  onAfterRunFiles?: (files: File[]) => unknown;
  /**
   * Appelé lorsqu'un nouveau contexte pour un test est défini. C'est utile si vous souhaitez ajouter des propriétés personnalisées au contexte.
   * Si votre seul objectif est de définir un contexte personnalisé avec un *runner*, envisagez plutôt d'utiliser "beforeAll" dans "setupFiles".
   */
  extendTaskContext?: (context: TestContext) => TestContext;
  /**
   * Appelé lors de l'importation de certains fichiers. Cette méthode peut être invoquée dans deux situations : pour collecter des tests et pour importer des fichiers de configuration.
   */
  importFile: (filepath: string, source: VitestRunnerImportSource) => unknown;
  /**
   * Fonction appelée lorsque le *runner* tente d'obtenir la valeur, notamment quand `test.extend` est utilisé avec `{ injected: true }`.
   */
  injectValue?: (key: string) => unknown;
  /**
   * Configuration accessible publiquement.
   */
  config: VitestRunnerConfig;
  /**
   * Le nom du pool actuel. Peut influencer la manière dont la trace de pile est déduite côté serveur.
   */
  pool?: string;
}

Lors de l'initialisation de cette classe, Vitest transmet sa configuration ; vous devez l'exposer en tant que propriété config :

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 injecte également une instance de ViteNodeRunner sous la propriété __vitest_executor. Vous pouvez l'utiliser pour traiter les fichiers dans la méthode importFile (c'est le comportement par défaut de TestRunner et BenchmarkRunner).

ViteNodeRunner expose la méthode executeId, utilisée pour importer des fichiers de test dans un environnement compatible Vite. Autrement dit, elle résoudra les importations et transformera le contenu du fichier à l'exécution pour que Node puisse le comprendre :

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

WARNING

Si vous n'avez pas de runner personnalisé ou si vous n'avez pas défini la méthode runTask, Vitest tentera de récupérer une tâche automatiquement. Si vous n'avez pas ajouté de fonction avec setFn, l'opération échouera.

TIP

La prise en charge des snapshots et d'autres fonctionnalités dépend du runner. Pour ne pas les perdre, vous pouvez étendre votre runner à partir de VitestTestRunner importé de vitest/runners. Il expose également BenchmarkNodeRunner, si vous souhaitez étendre les fonctionnalités de benchmark.

Tâches ​

WARNING

L'API des tâches du Runner est expérimentale et ne doit être utilisée principalement que dans l'environnement d'exécution des tests. Vitest expose également l'"API des tâches rapportées", qui est à privilégier lors de l'utilisation dans le thread principal (par exemple, à l'intérieur du rapporteur).

L'équipe discute actuellement de savoir si les "Tâches du Runner" devraient être remplacées par les "Tâches rapportées" à l'avenir.

Les suites et les tests sont appelés tasks en interne. Le runner Vitest initialise une tâche File avant de collecter les tests ; il s'agit d'un sur-ensemble de Suite avec quelques propriétés supplémentaires. Cette tâche est disponible sur chaque tâche (y compris File) via la propriété file.

ts
interface File extends Suite {
  /**
   * Le nom du pool auquel le fichier appartient.
   * @default 'forks'
   */
  pool?: string;
  /**
   * Le chemin d'accès au fichier au format UNIX.
   */
  filepath: string;
  /**
   * Le nom du projet de test auquel le fichier appartient.
   */
  projectName: string | undefined;
  /**
   * La durée nécessaire pour collecter tous les tests dans le fichier.
   * Ce temps inclut également l'importation de toutes les dépendances du fichier.
   */
  collectDuration?: number;
  /**
   * La durée nécessaire pour importer le fichier de configuration.
   */
  setupDuration?: number;
}

Chaque suite possède une propriété tasks qui est renseignée pendant la phase de collecte. Il est utile de parcourir l'arbre des tâches du haut vers le bas.

ts
interface Suite extends TaskBase {
  type: 'suite';
  /**
   * Tâche de fichier. Il s'agit de la tâche racine du fichier.
   */
  file: File;
  /**
   * Un tableau de tâches qui font partie de la suite.
   */
  tasks: Task[];
}

Chaque tâche possède une propriété suite qui référence la suite à laquelle elle appartient. Si test ou describe sont initiés au niveau supérieur, ils n'auront pas de propriété suite (elle ne sera pas égale à file !). De même, File n'a jamais de propriété suite. Il est utile de parcourir les tâches du bas vers le haut.

ts
interface Test<ExtraContext = object> extends TaskBase {
  type: 'test';
  /**
   * Contexte de test qui sera passé à la fonction de test.
   */
  context: TestContext & ExtraContext;
  /**
   * Tâche de fichier. Il s'agit de la tâche racine du fichier.
   */
  file: File;
  /**
   * Indique si la tâche a été ignorée en appelant `context.skip()`.
   */
  pending?: boolean;
  /**
   * Indique si la tâche doit réussir si elle échoue. Si la tâche échoue, elle sera marquée comme réussie.
   */
  fails?: boolean;
  /**
   * Stocke les promesses (issues des attentes asynchrones) afin de les attendre avant de terminer le test.
   */
  promises?: Promise<any>[];
}

Chaque tâche peut avoir un champ result. Les suites ne peuvent avoir ce champ que si une erreur levée dans un rappel de suite ou dans les rappels beforeAll/afterAll les empêche de collecter les tests. Les tests ont toujours ce champ après l'appel de leurs rappels ; les champs state et errors sont présents en fonction du résultat. Si une erreur a été levée dans les rappels beforeEach ou afterEach, l'erreur sera présente dans task.result.errors.

ts
export interface TaskResult {
  /**
   * État de la tâche. Hérite du `task.mode` pendant la collecte.
   * Lorsque la tâche est terminée, elle passera à `pass` ou `fail`.
   * - **pass**: la tâche s'est exécutée avec succès
   * - **fail**: la tâche a échoué
   */
  state: TaskState;
  /**
   * Erreurs survenues pendant l'exécution de la tâche. Il est possible d'avoir plusieurs erreurs
   * si `expect.soft()` a échoué plusieurs fois.
   */
  errors?: ErrorWithDiff[];
  /**
   * Durée d'exécution de la tâche en millisecondes.
   */
  duration?: number;
  /**
   * Heure de début de l'exécution de la tâche en millisecondes.
   */
  startTime?: number;
  /**
   * Taille du tas en octets après la fin de la tâche.
   * Disponible uniquement si l'option `logHeapUsage` est définie et que `process.memoryUsage` l'est également.
   */
  heap?: number;
  /**
   * État des hooks liés à cette tâche. Utile pour la génération de rapports.
   */
  hooks?: Partial<
    Record<'afterAll' | 'beforeAll' | 'beforeEach' | 'afterEach', TaskState>
  >;
  /**
   * Le nombre de fois où la tâche a été réessayée. La tâche n'est réessayée que si elle
   * a échoué et que l'option `retry` est définie.
   */
  retryCount?: number;
  /**
   * Le nombre de fois où la tâche a été répétée. La tâche n'est répétée que si
   * l'option `repeats` est définie. Ce nombre inclut également `retryCount`.
   */
  repeatCount?: number;
}

Votre fonction de tâche ​

Vitest expose l'utilitaire createTaskCollector pour créer votre propre méthode test. Elle se comporte de la même manière qu'un test, mais appelle une méthode personnalisée pendant la collecte.

Une tâche est un objet qui fait partie d'une suite. Elle est automatiquement ajoutée à la suite actuelle avec la méthode suite.task :

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

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

// cette fonction sera appelée pendant la phase de collecte :
// n'appelez pas le gestionnaire de fonction ici, ajoutez-le aux tâches de la suite
// avec la méthode "getCurrentSuite().task()"
// note : createTaskCollector prend en charge "todo"/"each"/...
export const myCustomTask = createTaskCollector(function (name, fn, timeout) {
  getCurrentSuite().task(name, {
    ...this, // pour que "todo"/"skip"/... soit suivi correctement
    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
Page précédenteAPI des plugins
Page suivanteRapporteurs

Publié sous la licence MIT.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/advanced/runner

Publié sous la licence MIT.

Copyright (c) 2021-Present Vitest Team