報告器 API
WARNING
這是一個進階 API。如果您只想設定內建報告器,請參閱 "報告器" 指南。
Vitest 擁有其獨特的測試執行生命週期。這些生命週期階段由報告器的方法所代表:
onInit
onTestRunStart
onTestRunEnd
單一模組內的測試與測試套件將依序報告,除非它們被跳過。所有被跳過的測試都會在測試套件/模組結束時報告。
請注意,由於測試模組可以並行執行,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>;
此方法在以下任何鉤子開始執行時被呼叫:
beforeAll
afterAll
beforeEach
afterEach
如果 beforeAll
或 afterAll
開始執行,entity
將是 TestSuite
或 TestModule
。
如果 beforeEach
或 afterEach
開始執行,entity
將始終是 TestCase
。
WARNING
如果鉤子在測試執行期間未執行,則不會呼叫 onHookStart
方法。
onHookEnd
function onHookEnd(context: ReportedHookContext): Awaitable<void>;
此方法在以下任何鉤子執行完成時被呼叫:
beforeAll
afterAll
beforeEach
afterEach
如果 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
屬性以引用該路徑。