Skip to content
Vitest 2
Main Navigation 指南API配置瀏覽器模式高級
3.2.0
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

測試執行器

任務元數據

擴充報告器

自訂池

本頁導覽

測試執行器 ​

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;
  /**
   * 在實際執行測試函式之前呼叫。此時已經有帶有 "state" 和 "startTime" 的 "result"。
   */
  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;
  /**
   * 當定義新的測試上下文時呼叫。如果您想向上下文添加自訂屬性,這會很有用。
   * 如果您只想使用執行器定義自訂上下文,請考慮改用 "setupFiles" 中的 "beforeAll"。
   *
   * 此方法會針對 "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

快照支援及其他一些功能取決於執行器。如果您不想失去它們,可以從 vitest/runners 匯入的 VitestTestRunner 擴充您的執行器。如果您想擴充基準測試功能,它也暴露了 BenchmarkNodeRunner。

任務 ​

套件和測試在內部稱為 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[];
  /**
   * 儲存 Promise (來自非同步期望),以便在完成測試之前等待它們
   */
  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) 2021-Present Vitest Team

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

以 MIT 授權條款 發布。

版權所有 (c) 2021-Present Vitest Team