Skip to content
Vitest 2
Main Navigation РуководствоAPIКонфигурацияРежим браузераПродвинутый
2.1.9
1.6.1
0.34.6

Русский

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

Русский

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

Внешний вид

Sidebar Navigation

Node API

Test Runner

Метаданные задач

Расширение репортеров

Кастомный пул

Содержание страницы

Исполнитель тестов ​

WARNING

Это продвинутый API. Если вы просто хотите запустить тесты, вам, вероятно, это не нужно. В основном он предназначен для авторов библиотек.

Вы можете указать путь к вашему исполнителю тестов с помощью опции runner в вашем файле конфигурации. Этот файл должен иметь экспорт по умолчанию в виде конструктора класса, реализующего следующие методы:

ts
export interface VitestRunner {
  /**
   * Вызывается первым перед фактическим сбором и запуском тестов.
   */
  onBeforeCollect?: (paths: string[]) => unknown;
  /**
   * Вызывается после сбора тестов и перед вызовом "onBeforeRun".
   */
  onCollected?: (files: File[]) => unknown;

  /**
   * Вызывается, когда исполнитель тестов должен отменить последующие запуски тестов.
   * Исполнитель должен реагировать на вызов этого метода и помечать тесты и наборы как пропущенные в
   * "onBeforeRunSuite" и "onBeforeRunTask" при вызове.
   */
  onCancel?: (reason: CancelReason) => unknown;

  /**
   * Вызывается перед запуском одного теста. Поле "result" еще отсутствует.
   */
  onBeforeRunTest?: (test: TaskPopulated) => unknown;
  /**
   * Вызывается перед фактическим запуском функции теста. Уже имеет поле "result" с полями "state" и "startTime".
   */
  onBeforeTryTask?: (
    test: TaskPopulated,
    options: { retry: number; repeats: number }
  ) => unknown;
  /**
   * Вызывается после установки результата и состояния.
   */
  onAfterRunTask?: (test: TaskPopulated) => unknown;
  /**
   * Вызывается сразу после запуска функции теста. Новое состояние еще не установлено. Не будет вызван, если функция теста выбросит исключение.
   */
  onAfterTryTask?: (
    test: TaskPopulated,
    options: { retry: number; repeats: number }
  ) => unknown;

  /**
   * Вызывается перед запуском одного набора. Поле "result" еще отсутствует.
   */
  onBeforeRunSuite?: (suite: Suite) => unknown;
  /**
   * Вызывается после запуска одного набора. Имеет установленное состояние и результат.
   */
  onAfterRunSuite?: (suite: Suite) => unknown;

  /**
   * Если определено, будет вызвано вместо стандартного разделения и обработки наборов Vitest.
   * Обработчики "before" и "after" не будут проигнорированы.
   */
  runSuite?: (suite: Suite) => Promise<void>;
  /**
   * Если определено, будет вызвано вместо стандартной обработки Vitest. Полезно, если у вас есть собственная функция теста.
   * Обработчики "before" и "after" не будут проигнорированы.
   */
  runTask?: (test: TaskPopulated) => Promise<void>;

  /**
   * Вызывается при обновлении задачи. Аналогично "onTaskUpdate" в репортере, но выполняется в том же потоке, что и тесты.
   */
  onTaskUpdate?: (task: [string, TaskResult | undefined][]) => Promise<void>;

  /**
   * Вызывается перед запуском всех тестов в указанных путях.
   */
  onBeforeRunFiles?: (files: File[]) => unknown;
  /**
   * Вызывается сразу после запуска всех тестов в указанных путях.
   */
  onAfterRunFiles?: (files: File[]) => unknown;
  /**
   * Вызывается при определении нового контекста для теста. Полезно, если вы хотите добавить собственные свойства в контекст.
   * Если вы хотите определить собственный контекст только с помощью исполнителя, рассмотрите возможность использования "beforeAll" в "setupFiles".
   *
   * Этот метод вызывается как для обработчиков "test", так и для "custom".
   *
   * @see https://www.getbook.com/en/book/vitest-2/advanced/runner#your-task-function
   */
  extendTaskContext?: <T extends Test | Custom>(
    context: TaskContext<T>
  ) => TaskContext<T>;
  /**
   * Вызывается при импорте определенных файлов. Может быть вызван в двух ситуациях: при сборе тестов и при импорте файлов настройки.
   */
  importFile: (filepath: string, source: VitestRunnerImportSource) => unknown;
  /**
   * Публичная конфигурация.
   */
  config: VitestRunnerConfig;
}

При инициализации этого класса Vitest передает конфигурацию Vitest - вы должны предоставить доступ к ней через свойство config.

WARNING

Vitest также предоставляет экземпляр ViteNodeRunner как свойство __vitest_executor. Вы можете использовать его для обработки файлов в методе importFile (это поведение по умолчанию для TestRunner и BenchmarkRunner).

ViteNodeRunner предоставляет метод executeId, который используется для импорта тестовых файлов в среде, совместимой с Vite. Это означает, что он будет разрешать импорты и преобразовывать содержимое файла во время выполнения, чтобы Node мог его выполнить.

TIP

Поддержка снимков и некоторые другие функции зависят от исполнителя. Если вы не хотите их потерять, вы можете унаследовать свой исполнитель от VitestTestRunner, импортированного из vitest/runners. Он также предоставляет доступ к BenchmarkNodeRunner, если вы хотите расширить функциональность бенчмарков.

Задачи ​

Наборы (Suites) и тесты внутренне называются tasks. Исполнитель Vitest создает задачу File перед сбором любых тестов - это надмножество Suite с несколькими дополнительными свойствами. Эта задача доступна для каждой задачи (включая File) как свойство file.

ts
interface File extends Suite {
  /**
   * Название пула, к которому принадлежит файл.
   * @default 'forks'
   */
  pool?: string;
  /**
   * Путь к файлу в формате пути UNIX.
   */
  filepath: string;
  /**
   * Название проекта рабочей области, к которому принадлежит файл.
   */
  projectName: string | undefined;
  /**
   * Время в миллисекундах для сбора всех тестов в файле.
   * Это время также включает загрузку всех зависимостей файла.
   */
  collectDuration?: number;
  /**
   * Время в миллисекундах для импорта файла настройки.
   */
  setupDuration?: number;
  /**
   * Указывает, был ли файл создан без запуска каких-либо тестов.
   * Это делается для инициализации состояния на стороне сервера Vitest.
   */
  local?: boolean;
}

Каждый набор имеет свойство tasks, которое формируется на этапе сбора. Это полезно для обхода иерархии задач сверху вниз.

ts
interface Suite extends TaskBase {
  type: 'suite';
  /**
   * Задача файла. Это корневая задача файла.
   */
  file: File;
  /**
   * Массив задач, входящих в набор.
   */
  tasks: Task[];
}

Каждая задача имеет свойство suite, которое указывает на набор, в котором она находится. Если test или describe создаются на верхнем уровне, у них не будет свойства suite (оно не будет равно file!). File также никогда не имеет свойства suite. Это полезно для обхода иерархии задач снизу вверх.

ts
interface Test<ExtraContext = object> extends TaskBase {
  type: 'test';
  /**
   * Контекст теста, который будет передан функции теста.
   */
  context: TaskContext<Test> & ExtraContext & TestContext;
  /**
   * Задача файла. Это корневая задача файла.
   */
  file: File;
  /**
   * Указывает, была ли задача пропущена вызовом `t.skip()`.
   */
  pending?: boolean;
  /**
   * Указывает, должна ли задача считаться успешной, если она завершилась с ошибкой. Если задача завершается с ошибкой, она будет помечена как пройденная.
   */
  fails?: boolean;
  /**
   * Обработчики, которые будут выполнены, если задача завершится с ошибкой. Порядок зависит от опции `sequence.hooks`.
   */
  onFailed?: OnTestFailedHandler[];
  /**
   * Обработчики, которые будут выполнены после завершения задачи. Порядок зависит от опции `sequence.hooks`.
   */
  onFinished?: OnTestFinishedHandler[];
  /**
   * Хранит промисы (например, из асинхронных expect), чтобы дождаться их перед завершением теста.
   */
  promises?: Promise<any>[];
}

Каждая задача может иметь поле result. Наборы могут иметь это поле только в том случае, если ошибка, выброшенная в колбэке набора или в колбэках beforeAll/afterAll, помешала сбору тестов. Тесты всегда имеют это поле после вызова их колбэков - поля state и errors присутствуют в зависимости от исхода выполнения. Если ошибка была выброшена в колбэках beforeEach или afterEach, выброшенная ошибка будет присутствовать в task.result.errors.

ts
export interface TaskResult {
  /**
   * Состояние задачи. Устанавливается на основе `task.mode` во время сбора.
   * Когда задача завершена, оно изменится на `pass` или `fail`.
   * - **pass**: задача выполнена успешно
   * - **fail**: задача завершилась с ошибкой
   */
  state: TaskState;
  /**
   * Ошибки, возникшие во время выполнения задачи. Может содержать несколько ошибок,
   * если `expect.soft()` завершился с ошибкой несколько раз.
   */
  errors?: ErrorWithDiff[];
  /**
   * Время в миллисекундах для выполнения задачи.
   */
  duration?: number;
  /**
   * Время в миллисекундах, когда задача начала выполняться.
   */
  startTime?: number;
  /**
   * Размер кучи в байтах после завершения задачи.
   * Доступно только если установлена опция `logHeapUsage` и определен `process.memoryUsage`.
   */
  heap?: number;
  /**
   * Состояние обработчиков, связанных с этой задачей. Полезно при составлении отчетов.
   */
  hooks?: Partial<
    Record<'afterAll' | 'beforeAll' | 'beforeEach' | 'afterEach', TaskState>
  >;
  /**
   * Количество раз, когда задача была повторена. Задача повторяется только в том случае, если
   * она завершилась с ошибкой и установлена опция `retry`.
   */
  retryCount?: number;
  /**
   * Количество раз, когда задача была выполнена повторно. Задача выполняется повторно только в том случае, если
   * установлена опция `repeats`. Это число также включает `retryCount`.
   */
  repeatCount?: number;
}

Ваша функция задачи ​

Vitest предоставляет тип задачи Custom, который позволяет пользователям повторно использовать встроенные репортеры. Он практически такой же, как Test, но имеет тип 'custom'.

Задача - это объект, который является частью набора. Он автоматически добавляется к текущему набору с помощью метода suite.task:

js
// ./utils/custom.js
import { createTaskCollector, getCurrentSuite, setFn } from 'vitest/suite';

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

// эта функция будет вызвана на этапе сбора:
// не вызывайте здесь функцию-обработчик, добавьте ее к задачам набора
// с помощью метода "getCurrentSuite().task()"
// примечание: createTaskCollector обеспечивает поддержку "todo"/"each"/...
export const myCustomTask = createTaskCollector(function (name, fn, timeout) {
  getCurrentSuite().task(name, {
    ...this, // чтобы "todo"/"skip"/... отслеживались правильно
    meta: {
      customPropertyToDifferentiateTask: true,
    },
    handler: fn,
    timeout,
  });
});
js
// ./garden/tasks.test.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

WARNING

Если у вас нет собственного исполнителя или вы не определили метод runTest, Vitest попытается получить задачу автоматически. Если вы не добавили функцию с помощью setFn, это приведет к ошибке.

Pager
Предыдущая страницаNode API
Следующая страницаМетаданные задач

Выпущено на условиях лицензии MIT.

Авторские права (c) 2024 Mithril Contributors

https://v2.vitest.dev/advanced/runner

Выпущено на условиях лицензии MIT.

Авторские права (c) 2024 Mithril Contributors