Skip to content

Bun 的測試運行器現在支持內置代碼覆蓋率報告。這使得查看代碼庫中有多少被測試覆蓋以及查找當前未得到充分測試的區域變得容易。

啟用覆蓋率

bun:test 支持查看哪些代碼行被測試覆蓋。要使用此功能,請在 CLI 中傳遞 --coverage。它將在控制台打印覆蓋率報告:

bash
bun test --coverage

-------------|---------|---------|-------------------
File         | % Funcs | % Lines | Uncovered Line #s
-------------|---------|---------|-------------------
All files    |   38.89 |   42.11 |
 index-0.ts  |   33.33 |   36.84 | 10-15,19-24
 index-1.ts  |   33.33 |   36.84 | 10-15,19-24
 index-10.ts |   33.33 |   36.84 | 10-15,19-24
 index-2.ts  |   33.33 |   36.84 | 10-15,19-24
 index-3.ts  |   33.33 |   36.84 | 10-15,19-24
 index-4.ts  |   33.33 |   36.84 | 10-15,19-24
 index-5.ts  |   33.33 |   36.84 | 10-15,19-24
 index-6.ts  |   33.33 |   36.84 | 10-15,19-24
 index-7.ts  |   33.33 |   36.84 | 10-15,19-24
 index-8.ts  |   33.33 |   36.84 | 10-15,19-24
 index-9.ts  |   33.33 |   36.84 | 10-15,19-24
 index.ts    |  100.00 |  100.00 |
-------------|---------|---------|-------------------

默認啟用

要始終默認啟用覆蓋率報告,請在 bunfig.toml 中添加以下行:

toml
[test]
# 始終啟用覆蓋率
coverage = true

默認情況下,覆蓋率報告將包含測試文件並排除 sourcemaps。這通常是你想要的,但也可以在 bunfig.toml 中進行配置。

toml
[test]
coverageSkipTestFiles = true  # 默認 false

覆蓋率閾值

可以在 bunfig.toml 中指定覆蓋率閾值。如果你的測試套件未達到或超過此閾值,bun test 將以非零退出碼退出以指示失敗。

簡單閾值

toml
[test]
# 要求 90% 的行級和函數級覆蓋率
coverageThreshold = 0.9

詳細閾值

toml
[test]
# 為行和函數設置不同的閾值
coverageThreshold = { lines = 0.9, functions = 0.9, statements = 0.9 }

設置任何這些閾值將啟用 fail_on_low_coverage,如果覆蓋率低於閾值,測試運行將失敗。

覆蓋率報告器

默認情況下,覆蓋率報告將打印到控制台。

對於 CI 環境和其他工具中的持久代碼覆蓋率報告,你可以傳遞 --coverage-reporter=lcov CLI 選項或在 bunfig.toml 中使用 coverageReporter 選項。

toml
[test]
coverageReporter = ["text", "lcov"]  # 默認 ["text"]
coverageDir = "path/to/somewhere"    # 默認 "coverage"

可用的報告器

報告器描述
text在控制台打印覆蓋率的文本摘要
lcov以 lcov 格式保存覆蓋率

LCOV 覆蓋率報告器

要生成 lcov 報告,你可以使用 lcov 報告器。這將在 coverage 目錄中生成一個 lcov.info 文件。

toml
[test]
coverageReporter = "lcov"
bash
# 或通過 CLI
bun test --coverage --coverage-reporter=lcov

LCOV 格式被各種工具和服務廣泛支持:

  • 代碼編輯器:VS Code 擴展可以內聯顯示覆蓋率
  • CI/CD 服務:GitHub Actions、GitLab CI、CircleCI
  • 覆蓋率服務:Codecov、Coveralls
  • IDE:WebStorm、IntelliJ IDEA

在 GitHub Actions 中使用 LCOV

yaml
name: Test with Coverage
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: oven-sh/setup-bun@v2
      - run: bun install
      - run: bun test --coverage --coverage-reporter=lcov
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/lcov.info

從覆蓋率中排除文件

跳過測試文件

默認情況下,測試文件本身包含在覆蓋率報告中。你可以使用以下方法排除它們:

toml
[test]
coverageSkipTestFiles = true  # 默認 false

這將排除與測試模式匹配的文件(例如 *.test.ts*.spec.js)不顯示在覆蓋率報告中。

忽略特定路徑和模式

你可以使用 coveragePathIgnorePatterns 從覆蓋率報告中排除特定文件或文件模式:

toml
[test]
# 單個模式
coveragePathIgnorePatterns = "**/*.spec.ts"

# 多個模式
coveragePathIgnorePatterns = [
  "**/*.spec.ts",
  "**/*.test.ts",
  "src/utils/**",
  "*.config.js"
]

此選項接受 glob 模式,工作方式類似於 Jest 的 collectCoverageFrom 忽略模式。與任何這些模式匹配的文件將從文本和 LCOV 輸出中的覆蓋率計算和報告中排除。

常見用例

toml
[test]
coveragePathIgnorePatterns = [
  # 排除工具文件
  "src/utils/**",

  # 排除配置文件
  "*.config.js",
  "webpack.config.ts",
  "vite.config.ts",

  # 排除特定測試模式
  "**/*.spec.ts",
  "**/*.e2e.ts",

  # 排除構建產物
  "dist/**",
  "build/**",

  # 排除生成的文件
  "src/generated/**",
  "**/*.generated.ts",

  # 排除供應商/第三方代碼
  "vendor/**",
  "third-party/**"
]

Sourcemaps

在內部,Bun 默認轉譯所有文件,因此 Bun 會自動生成一個內部 source map,將原始源代碼的行映射到 Bun 的內部表示。如果由於任何原因你想禁用此功能,請將 test.coverageIgnoreSourcemaps 設置為 true;這在高級用例之外很少需要。

toml
[test]
coverageIgnoreSourcemaps = true  # 默認 false

覆蓋率默認值

默認情況下,覆蓋率報告:

  • 排除 node_modules 目錄
  • 排除 通過非 JS/TS 加載器加載的文件(例如 .css.txt),除非指定了自定義 JS 加載器
  • 包含 測試文件本身(可以使用 coverageSkipTestFiles = true 禁用)
  • 可以使用 coveragePathIgnorePatterns 排除其他文件

高級配置

自定義覆蓋率目錄

toml
[test]
coverageDir = "coverage-reports"  # 默認 "coverage"

多個報告器

toml
[test]
coverageReporter = ["text", "lcov"]

使用特定測試模式的覆蓋率

bash
# 僅對特定測試文件運行覆蓋率
bun test --coverage src/components/*.test.ts

# 使用名稱模式運行覆蓋率
bun test --coverage --test-name-pattern="API"

CI/CD 集成

GitHub Actions 示例

yaml
name: Coverage Report
on: [push, pull_request]

jobs:
  coverage:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Bun
        uses: oven-sh/setup-bun@v2

      - name: Install dependencies
        run: bun install

      - name: Run tests with coverage
        run: bun test --coverage --coverage-reporter=lcov

      - name: Upload to Codecov
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/lcov.info
          fail_ci_if_error: true

GitLab CI 示例

yaml
test:coverage:
  stage: test
  script:
    - bun install
    - bun test --coverage --coverage-reporter=lcov
  coverage: '/Lines\s*:\s*(\d+.\d+)%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/lcov.info

解釋覆蓋率報告

文本輸出解釋

-------------|---------|---------|-------------------
File         | % Funcs | % Lines | Uncovered Line #s
-------------|---------|---------|-------------------
All files    |   85.71 |   90.48 |
 src/        |   85.71 |   90.48 |
  utils.ts   |  100.00 |  100.00 |
  api.ts     |   75.00 |   85.71 | 15-18,25
  main.ts    |   80.00 |   88.89 | 42,50-52
-------------|---------|---------|-------------------
  • % Funcs:測試期間調用的函數百分比
  • % Lines:測試期間運行的可執行行百分比
  • Uncovered Line #s:未執行的具體行號

目標覆蓋率

  • 80%+ 整體覆蓋率:通常被認為是好的
  • 90%+ 關鍵路徑:重要的業務邏輯應該得到充分測試
  • 100% 工具函數:純函數和工具函數很容易完全測試
  • UI 組件的較低覆蓋率:通常可以接受,因為它們可能需要集成測試

最佳實踐

關注質量,而不僅僅是數量

ts
// 好:測試實際功能
test("calculateTax 應該處理不同的稅率", () => {
  expect(calculateTax(100, 0.08)).toBe(8);
  expect(calculateTax(100, 0.1)).toBe(10);
  expect(calculateTax(0, 0.08)).toBe(0);
});

// 避免:只是為了覆蓋而行
test("calculateTax 存在", () => {
  calculateTax(100, 0.08); // 沒有斷言!
});

測試邊界情況

ts
test("用戶輸入驗證", () => {
  // 測試正常情況
  expect(validateEmail("user@example.com")).toBe(true);

  // 測試有意義地提高覆蓋率的邊界情況
  expect(validateEmail("")).toBe(false);
  expect(validateEmail("invalid")).toBe(false);
  expect(validateEmail(null)).toBe(false);
});

使用覆蓋率查找缺失的測試

bash
# 運行覆蓋率以識別未經測試的代碼
bun test --coverage

# 查看需要關注的具體文件
bun test --coverage src/critical-module.ts

與其他質量指標結合

覆蓋率只是一個指標。還要考慮:

  • 代碼審查質量
  • 集成測試覆蓋率
  • 錯誤處理測試
  • 性能測試
  • 類型安全

故障排除

某些文件未顯示覆蓋率

如果文件未出現在覆蓋率報告中,它們可能未被測試導入。覆蓋率僅跟蹤實際加載的文件。

ts
# 確保導入要測試的模塊
import { myFunction } from "../src/my-module";

test("我的函數有效", () => {
  expect(myFunction()).toBeDefined();
});

錯誤的覆蓋率報告

如果你看到與預期不符的覆蓋率報告:

  1. 檢查 source map 是否正常工作
  2. 驗證 coveragePathIgnorePatterns 中的文件模式
  3. 確保測試文件實際導入了要測試的代碼

大型代碼庫的性能問題

對於大型項目,覆蓋率收集可能會減慢測試速度:

toml
[test]
# 排除你不需要覆蓋率的大型目錄
coveragePathIgnorePatterns = [
  "node_modules/**",
  "vendor/**",
  "generated/**"
]

考慮僅在 CI 或特定分支上運行覆蓋率,而不是在開發期間每次測試運行。

Bun學習網由www.bunjs.com.cn整理維護