報告器 API
WARNING
這是一個進階 API。如果您只想設定內建報告器,請參閱 "報告器" 指南。
Vitest 擁有其獨特的測試執行生命週期。這些生命週期階段由報告器的方法所代表:
onInitonTestRunStartonTestRunEnd
單一模組內的測試與測試套件將依序報告,除非它們被跳過。所有被跳過的測試都會在測試套件/模組結束時報告。
請注意,由於測試模組可以並行執行,Vitest 也會並行地報告其結果。
本指南列出了所有支援的報告器方法。然而,請記住,您可以 擴展現有的報告器,而非從頭創建:
import { BaseReporter } from 'vitest/reporters';
export default class CustomReporter extends BaseReporter {
onTestRunEnd(testModules, errors) {
console.log(testModule.length, 'tests finished running');
super.onTestRunEnd(testModules, errors);
}
}onInit
function onInit(vitest: Vitest): Awaitable<void>;此方法在 Vitest 初始化或啟動時呼叫,但在測試篩選之前。
INFO
在 Vitest 內部,此方法會在 vitest.start、vitest.init 或 vitest.mergeReports 內部呼叫。如果您使用程式化介面 (API),請確保根據您的需求呼叫其中一個,例如在呼叫 vitest.runTestSpecifications 之前。內建的 CLI 將始終以正確的順序執行這些方法。
請注意,您也可以透過 project 屬性從測試案例、套件和測試模組中存取 vitest 實例,但在此方法中儲存 vitest 實例的參考也可能很有用。
範例
import type { Reporter, TestSpecification, Vitest } from 'vitest/node';
class MyReporter implements Reporter {
private vitest!: Vitest;
onInit(vitest: Vitest) {
this.vitest = vitest;
}
onTestRunStart(specifications: TestSpecification[]) {
console.log(
specifications.length,
'test files will run in',
this.vitest.config.root
);
}
}
export default new MyReporter();onBrowserInit 實驗性
function onBrowserInit(project: TestProject): Awaitable<void>;此方法在瀏覽器實例初始化時呼叫。它會接收到該瀏覽器所屬的專案實例。當此方法被呼叫時,project.browser 將始終被定義。
onTestRunStart
function onTestRunStart(specifications: TestSpecification[]): Awaitable<void>;此方法在新的測試執行開始時呼叫。它接收一個排定執行的 測試規格 陣列。此陣列是唯讀的,僅供資訊參考。
如果 Vitest 沒有找到任何要執行的測試檔案,此事件將以空陣列觸發,然後立即呼叫 onTestRunEnd。
範例
import type { Reporter, TestSpecification } from 'vitest/node';
class MyReporter implements Reporter {
onTestRunStart(specifications: TestSpecification[]) {
console.log(specifications.length, 'test files will run');
}
}
export default new MyReporter();棄用通知
此方法在 Vitest 3 中新增,取代了 onPathsCollected 和 onSpecsCollected,這兩者現已棄用。
onTestRunEnd
function onTestRunEnd(
testModules: ReadonlyArray<TestModule>,
unhandledErrors: ReadonlyArray<SerializedError>,
reason: TestRunEndReason
): Awaitable<void>;此方法在所有測試執行完成且在涵蓋率功能啟用時,合併所有報告後呼叫。請注意,您可以在 onCoverage 鉤子中獲取涵蓋率資訊。
它接收一個唯讀的測試模組列表。您可以透過 testModule.children 屬性迭代它來報告其狀態和任何錯誤。
第二個參數是 Vitest 無法歸因於任何測試的未處理錯誤的唯讀列表。這些錯誤可能發生在測試執行之外,因為外掛程式中存在錯誤,或者在測試執行內部作為非同步函數的副作用(例如,測試執行完成後拋出錯誤的超時)。
第三個參數指示了測試執行結束的原因:
passed:測試執行正常結束且未發生任何錯誤。failed:測試執行至少發生一個錯誤(由於收集階段的語法錯誤或測試執行期間的實際錯誤)。interrupted:測試被vitest.cancelCurrentRun呼叫中斷或在終端機中按下Ctrl+C(請注意,此情況下仍可能有失敗的測試)。
如果 Vitest 沒有找到任何要執行的測試檔案,此事件將以空的模組和錯誤陣列觸發,並且狀態將取決於 config.passWithNoTests 的值。
範例
import type {
Reporter,
SerializedError,
TestModule,
TestRunEndReason,
TestSpecification,
} from 'vitest/node';
class MyReporter implements Reporter {
onTestRunEnd(
testModules: ReadonlyArray<TestModule>,
unhandledErrors: ReadonlyArray<SerializedError>,
reason: TestRunEndReason
) {
if (reason === 'passed') {
testModules.forEach(module => console.log(module.moduleId, 'succeeded'));
} else if (reason === 'failed') {
// 請注意,這將會跳過測試套件中可能存在的錯誤
// 您可以從 testSuite.errors() 中獲取它們
for (const testCase of testModules.children.allTests()) {
if (testCase.result().state === 'failed') {
console.log(
testCase.fullName,
'in',
testCase.module.moduleId,
'failed'
);
console.log(testCase.result().errors);
}
}
} else {
console.log('test run was interrupted, skipping report');
}
}
}
export default new MyReporter();棄用通知
此方法在 Vitest 3 中新增,取代了 onFinished,後者現已棄用。
onCoverage
function onCoverage(coverage: unknown): Awaitable<void>;此鉤子在涵蓋率結果處理後呼叫。涵蓋率提供者的報告器會在該鉤子之後被呼叫。coverage 的型別取決於 coverage.provider。對於 Vitest 的預設內建提供者,您可以從 istanbul-lib-coverage 套件匯入類型:
import type { CoverageMap } from 'istanbul-lib-coverage';
declare function onCoverage(coverage: CoverageMap): Awaitable<void>;如果 Vitest 未執行任何涵蓋率分析,則不會呼叫此鉤子。
onTestModuleQueued
function onTestModuleQueued(testModule: TestModule): Awaitable<void>;此方法在 Vitest 匯入設定檔和測試模組本身之前呼叫。這表示 testModule 尚未包含任何 children,但您可以開始將其報告為下一個即將執行的測試。
onTestModuleCollected
function onTestModuleCollected(testModule: TestModule): Awaitable<void>;此方法在檔案內的所有測試都已收集完成時被呼叫,這表示 testModule.children 集合已填充完成,但測試尚未產生任何結果。
onTestModuleStart
function onTestModuleStart(testModule: TestModule): Awaitable<void>;此方法在 onTestModuleCollected 之後立即被呼叫,除非 Vitest 在收集模式下執行(CLI 中的 vitest.collect() 或 vitest collect),在這種情況下,它將完全不會被呼叫,因為沒有測試要執行。
onTestModuleEnd
function onTestModuleEnd(testModule: TestModule): Awaitable<void>;此方法在模組中的每個測試執行完成時被呼叫。這表示,testModule.children 中的每個測試都將有一個不為 pending 的 test.result()。
onHookStart
function onHookStart(context: ReportedHookContext): Awaitable<void>;此方法在以下任何鉤子開始執行時被呼叫:
beforeAllafterAllbeforeEachafterEach
如果 beforeAll 或 afterAll 開始執行,entity 將是 TestSuite 或 TestModule。
如果 beforeEach 或 afterEach 開始執行,entity 將始終是 TestCase。
WARNING
如果鉤子在測試執行期間未執行,則不會呼叫 onHookStart 方法。
onHookEnd
function onHookEnd(context: ReportedHookContext): Awaitable<void>;此方法在以下任何鉤子執行完成時被呼叫:
beforeAllafterAllbeforeEachafterEach
如果 beforeAll 或 afterAll 執行完成,entity 將是 TestSuite 或 TestModule。
如果 beforeEach 或 afterEach 執行完成,entity 將始終是 TestCase。
WARNING
如果鉤子在測試執行期間未執行,則不會呼叫 onHookEnd 方法。
onTestSuiteReady
function onTestSuiteReady(testSuite: TestSuite): Awaitable<void>;此方法在測試套件開始執行其測試之前被呼叫。即使測試套件被跳過,此方法也會被呼叫。
如果檔案不包含任何測試套件,則不會呼叫此方法。考慮使用 onTestModuleStart 來涵蓋此使用情境。
onTestSuiteResult
function onTestSuiteResult(testSuite: TestSuite): Awaitable<void>;此方法在測試套件執行測試完成後被呼叫。即使測試套件被跳過,此方法也會被呼叫。
如果檔案不包含任何測試套件,則不會呼叫此方法。考慮使用 onTestModuleEnd 來涵蓋此使用情境。
onTestCaseReady
function onTestCaseReady(testCase: TestCase): Awaitable<void>;此方法在測試開始執行或被跳過之前被呼叫。請注意,beforeEach 和 afterEach 鉤子被視為測試的一部分,因為它們可能會影響測試結果。
WARNING
請注意,當 onTestCaseReady 被呼叫時,testCase.result() 可能已經處於 passed 或 failed 狀態。這可能發生在測試執行速度過快的情況下,並且 onTestCaseReady 和 onTestCaseResult 都被排定在同一個微任務中執行時。
onTestCaseResult
function onTestCaseResult(testCase: TestCase): Awaitable<void>;此方法在測試執行完成或被跳過時被呼叫。請注意,如果存在 afterEach 鉤子,此方法將在 afterEach 鉤子執行完成後被呼叫。
此時,testCase.result() 將處於非待定狀態。
onTestAnnotate 3.2.0+
function onTestAnnotate(
testCase: TestCase,
annotation: TestAnnotation
): Awaitable<void>;onTestAnnotate 鉤子與 context.annotate 方法相關聯。當 annotate 被呼叫時,Vitest 會將其序列化並將相同的註解傳送到主執行緒,報告器可以在其中與其進行互動。
如果路徑被指定,Vitest 會將其儲存在單獨的目錄中(由 attachmentsDir 配置),並修改 path 屬性以引用該路徑。