程式碼覆蓋率
Vitest 支援透過 v8
進行原生程式碼覆蓋率收集,並透過 istanbul
進行檢測程式碼覆蓋率。
覆蓋率提供者
v8
和 istanbul
支援皆為可選。預設情況下,將使用 v8
。
您可以透過將 test.coverage.provider
設定為 v8
或 istanbul
來選擇覆蓋率工具:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
coverage: {
provider: 'istanbul', // 或 'v8'
},
},
});
當您啟動 Vitest 處理程序時,它會提示您自動安裝相應的支援套件。
或者,如果您偏好手動安裝:
npm i -D @vitest/coverage-v8
npm i -D @vitest/coverage-istanbul
V8 提供者
INFO
以下關於 V8 覆蓋率的描述為 Vitest 特有,不適用於其他測試執行器。 自 v3.2.0
起,Vitest 已將 基於 AST 的覆蓋率重新映射 用於 V8 覆蓋率,這會產生與 Istanbul 相同的覆蓋率報告。
這讓使用者能夠同時享有 V8 覆蓋率的速度與 Istanbul 覆蓋率的準確性。
預設情況下,Vitest 使用 'v8'
覆蓋率提供者。 此提供者需要基於 V8 引擎 實作的 JavaScript 執行環境,例如 NodeJS、Deno 或任何基於 Chromium 的瀏覽器(如 Google Chrome)。
覆蓋率收集是在執行時,透過使用 node:inspector
和瀏覽器中的 Chrome DevTools Protocol 來指示 V8 進行的。原始碼檔案可以按原樣執行,無需任何預先檢測步驟。
- ✅ 推薦使用的選項
- ✅ 無需預轉譯步驟。測試檔案可以按原樣執行。
- ✅ 執行時間比 Istanbul 快。
- ✅ 記憶體用量比 Istanbul 低。
- ✅ 覆蓋率報告準確性與 Istanbul 一樣好(自 Vitest
v3.2.0
起)。 - ⚠️ 在某些情況下可能比 Istanbul 慢,例如載入大量不同模組時。V8 不支援將覆蓋率收集限制於特定模組。
- ⚠️ V8 引擎設定了一些次要限制。請參閱
ast-v8-to-istanbl
| 限制。 - ❌ 不適用於不使用 V8 的環境(例如 Firefox 或 Bun),或不透過分析器公開 V8 覆蓋率的環境(例如 Cloudflare Workers)。
Istanbul 提供者
Istanbul 程式碼覆蓋率工具 自 2012 年以來一直存在,並經過了充分的實戰驗證。 此提供者適用於任何 JavaScript 執行環境,因為覆蓋率追蹤是透過檢測原始碼檔案來完成的。
實際上,檢測原始檔案意味著在使用者檔案中添加額外的 JavaScript:
// 分支和函數覆蓋率計數器的簡化範例
const coverage = {
branches: { 1: [0, 0] },
functions: { 1: 0 },
}
export function getUsername(id) {
// 當此函數被呼叫時,函數覆蓋率增加
coverage.functions['1']++;
if (id == null) {
// 當此分支被呼叫時,分支覆蓋率增加
coverage.branches['1'][0]++;
throw new Error('User ID is required');
}
// 當 if 語句條件不成立時,隱式 else 覆蓋率增加
coverage.branches['1'][1]++;
return database.getUser(id);
}
globalThis.__VITEST_COVERAGE__ ||= {};
globalThis.__VITEST_COVERAGE__[filename] = coverage;
- ✅ 適用於任何 JavaScript 執行環境
- ✅ 廣泛使用並經過 13 年以上的實戰驗證。
- ✅ 在某些情況下比 V8 快。覆蓋率檢測可以限制到特定檔案,而 V8 則檢測所有模組。
- ❌ 需要預檢測步驟
- ❌ 由於檢測開銷,執行速度比 V8 慢
- ❌ 檢測會增加檔案大小
- ❌ 記憶體用量比 V8 高
覆蓋率設定
TIP
建議您始終在設定檔中定義 coverage.include
。 這有助於 Vitest 減少 coverage.all
所選取的檔案數量。
若要啟用覆蓋率進行測試,您可以在 CLI 中傳遞 --coverage
標誌。 預設情況下,將使用報告器 ['text', 'html', 'clover', 'json']
。
{
"scripts": {
"test": "vitest",
"coverage": "vitest run --coverage"
}
}
若要設定它,請在您的設定檔中設定 test.coverage
選項:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
coverage: {
reporter: ['text', 'json', 'html'],
},
},
});
自訂覆蓋率報告器
您可以透過在 test.coverage.reporter
中傳遞套件名稱或絕對路徑來使用自訂覆蓋率報告器:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
coverage: {
reporter: [
// 使用 NPM 套件名稱指定報告器
['@vitest/custom-coverage-reporter', { someOption: true }],
// 使用本地路徑指定報告器
'/absolute/path/to/custom-reporter.cjs',
],
},
},
});
自訂報告器由 Istanbul 載入,並且必須實作其報告器介面。請參閱內建報告器的實作以供參考。
const { ReportBase } = require('istanbul-lib-report');
module.exports = class CustomReporter extends ReportBase {
constructor(opts) {
super();
// 從設定傳遞的選項可在此處取得
this.file = opts.file;
}
onStart(root, context) {
this.contentWriter = context.writer.writeFile(this.file);
this.contentWriter.println('自訂覆蓋率報告開始');
}
onEnd() {
this.contentWriter.println('自訂覆蓋率報告結束');
this.contentWriter.close();
}
};
自訂覆蓋率提供者
也可以透過在 test.coverage.provider
中傳遞 'custom'
來提供您的自訂覆蓋率提供者:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
coverage: {
provider: 'custom',
customProviderModule: 'my-custom-coverage-provider',
},
},
});
自訂提供者需要一個 customProviderModule
選項,它是一個模組名稱或路徑,用於載入 CoverageProviderModule
。它必須預設匯出一個實作 CoverageProviderModule
的物件:
import type {
CoverageProvider,
CoverageProviderModule,
ResolvedCoverageOptions,
Vitest,
} from 'vitest';
const CustomCoverageProviderModule: CoverageProviderModule = {
getProvider(): CoverageProvider {
return new CustomCoverageProvider();
},
// 實作 CoverageProviderModule 的其餘部分 ...
};
class CustomCoverageProvider implements CoverageProvider {
name = 'custom-coverage-provider';
options!: ResolvedCoverageOptions;
initialize(ctx: Vitest) {
this.options = ctx.config.coverage;
}
// 實作 CoverageProvider 的其餘部分 ...
}
export default CustomCoverageProviderModule;
請參閱類型定義以獲取更多詳細資訊。
變更預設覆蓋率資料夾位置
執行覆蓋率報告時,會在專案的根目錄中建立一個 coverage
資料夾。如果您想將其移動到不同的目錄,請在 vitest.config.js
檔案中使用 test.coverage.reportsDirectory
屬性。
import { defineConfig } from 'vite';
export default defineConfig({
test: {
coverage: {
reportsDirectory: './tests/unit/coverage',
},
},
});
忽略程式碼
兩種覆蓋率提供者都有各自從覆蓋率報告中忽略程式碼的方式:
使用 TypeScript 時,原始碼會透過 esbuild
進行轉譯,這會從原始碼中刪除所有註解(esbuild#516)。 被視為合法註解的註解將會被保留。
您可以在忽略提示中包含 @preserve
關鍵字。 請注意,這些忽略提示現在也可能被包含在最終的生產建置中。
-/* istanbul ignore if */
+/* istanbul ignore if -- @preserve */
if (condition) {
-/* v8 ignore if */
+/* v8 ignore if -- @preserve */
if (condition) {
其他選項
要查看所有可設定的覆蓋率選項,請參閱覆蓋率設定參考。
覆蓋率效能
如果您的專案中程式碼覆蓋率生成很慢,請參閱分析測試效能 | 程式碼覆蓋率。
Vitest UI
您可以在 Vitest UI 中查看您的覆蓋率報告。
Vitest UI 將在明確啟用覆蓋率報告且存在 HTML 覆蓋率報告器時啟用覆蓋率報告,否則將無法使用:
- 在您的設定檔中啟用
coverage.enabled=true
,或使用--coverage.enabled=true
標誌執行 Vitest - 將
html
新增到coverage.reporter
列表中:您也可以啟用subdir
選項,將覆蓋率報告放置於子目錄中。



