> ## Documentation Index
> Fetch the complete documentation index at: https://bun.zhcndoc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 代码覆盖率

> 了解如何使用 Bun 内置的代码覆盖率报告来跟踪测试覆盖情况并发现代码库中未测试的区域

Bun 的测试运行器支持内置的代码覆盖率报告。使用它来查看你的代码库有多少被测试覆盖，并发现当前覆盖不充分的区域。

## 启用覆盖率

`bun:test` 支持查看哪些代码行被测试覆盖。要使用此功能，请在 CLI 传递 `--coverage`。它会将覆盖率报告打印到控制台：

```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
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 title="bunfig.toml" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
# 始终启用覆盖率
coverage = true
```

默认情况下，覆盖率报告会包含测试文件，并排除源码映射（sourcemaps）。这通常是你想要的，但也可以在 `bunfig.toml` 中进行其他配置。

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
coverageSkipTestFiles = true  # 默认 false
```

## 覆盖率阈值

可以在 `bunfig.toml` 中指定覆盖率阈值。如果测试套件没有达到或超过此阈值，`bun test` 将以非零退出码退出，表明测试失败。

### 简单阈值

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
# 要求 90% 的行级覆盖率和函数级覆盖率
coverageThreshold = 0.9
```

### 详细阈值

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
# 为行、函数和语句设置不同的阈值
coverageThreshold = { lines = 0.9, functions = 0.9, statements = 0.9 }
```

设置任何阈值都会启用 `fail_on_low_coverage`：如果覆盖率低于阈值，测试运行将失败。

## 覆盖率报告器

默认情况下，覆盖率报告会打印到控制台。

对于 CI 环境中需要持久化的代码覆盖率报告以及其他工具，你可以通过 CLI 传递 `--coverage-reporter=lcov` 选项，或者在 `bunfig.toml` 中设置 `coverageReporter` 选项。

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
coverageReporter = ["text", "lcov"]  # 默认 ["text"]
coverageDir = "path/to/somewhere"    # 默认 "coverage"
```

### 可用的报告器

| 报告器    | 说明             |
| ------ | -------------- |
| `text` | 在控制台打印覆盖率文本摘要  |
| `lcov` | 以 lcov 格式保存覆盖率 |

### LCOV 覆盖率报告器

要生成 lcov 报告，可以使用 lcov 报告器。这会在覆盖率目录生成一个 `lcov.info` 文件。

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
coverageReporter = "lcov"
```

```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
# 或通过 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 title=".github/workflows/test.yml" icon="file-code" theme={"theme":{"light":"github-light","dark":"dracula"}}
name: 带覆盖率的测试
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: 上传覆盖率到 Codecov
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/lcov.info
```

## 从覆盖率中排除文件

### 跳过测试文件

默认情况下，测试文件本身会包含在覆盖率报告中。你可以用以下方式将它们排除：

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
coverageSkipTestFiles = true  # 默认 false
```

这会将匹配测试模式的文件（例如 `*.test.ts`、`*.spec.js`）从覆盖率报告中排除。

### 忽略特定路径和模式

你可以使用 `coveragePathIgnorePatterns` 从覆盖率报告中排除特定文件或文件模式：

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
# 单个模式
coveragePathIgnorePatterns = "**/*.spec.ts"

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

此选项接受 glob 模式，类似于 Jest 的 `collectCoverageFrom` 忽略模式。符合任一模式的文件都会从覆盖率计算和报告中排除，包括文本和 LCOV 输出。

#### 常见用例

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[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 会自动生成一个内部源码映射，将你的原始源码行映射到 Bun 的内部表示。如果你想禁用此行为，可以设置 `test.coverageIgnoreSourcemaps` 为 `true`；除非是高级用例，否则很少需要这么做。

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
coverageIgnoreSourcemaps = true  # 默认 false
```

<Warning>
  使用此选项时，你可能需要在源码文件顶部加上 `// @bun` 注释，以避免被转译。
</Warning>

## 覆盖率默认行为

默认情况下，覆盖率报告：

* **排除** `node_modules` 目录
* **排除** 通过非 JS/TS 加载器加载的文件（例如 `.css`、`.txt`），除非你指定了自定义 JS 加载器
* **包含** 测试文件本身（可通过 `coverageSkipTestFiles = true` 禁用）
* 可以通过 `coveragePathIgnorePatterns` 进一步排除文件

## 高级配置

### 自定义覆盖率目录

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
coverageDir = "coverage-reports"  # 默认 "coverage"
```

### 多个报告器

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
coverageReporter = ["text", "lcov"]
```

### 针对特定测试模式启用覆盖率

```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
# 仅对特定测试文件运行覆盖率
bun test --coverage src/components/*.test.ts

# 针对名称模式运行覆盖率
bun test --coverage --test-name-pattern="API"
```

## CI/CD 集成

### GitHub Actions 示例

```yaml title=".github/workflows/coverage.yml" icon="file-code" theme={"theme":{"light":"github-light","dark":"dracula"}}
name: 覆盖率报告
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: 安装依赖
        run: bun install

      - name: 运行带覆盖率的测试
        run: bun test --coverage --coverage-reporter=lcov

      - name: 上传到 Codecov
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/lcov.info
          fail_ci_if_error: true
```

### GitLab CI 示例

```yaml title=".gitlab-ci.yml" theme={"theme":{"light":"github-light","dark":"dracula"}}
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**：测试覆盖的可执行代码行百分比
* **未覆盖的行号**：未执行的具体代码行号

### 目标标准

* **80% 及以上整体覆盖率**：通常认为表现良好
* **关键路径 90% 及以上**：关键业务逻辑应当被充分测试
* **工具函数 100%**：纯函数和工具函数更容易实现完全覆盖
* **UI 组件覆盖率较低**：通常可以接受，因为多数需要集成测试

## 最佳实践

### 注重质量而非数量

```ts title="test.ts" icon="https://mintcdn.com/bun-zhcndoc/cnUTwgMuf4cCrwC-/icons/typescript.svg?fit=max&auto=format&n=cnUTwgMuf4cCrwC-&q=85&s=e7767043c9e885c34f2d6c8fe2a95217" theme={"theme":{"light":"github-light","dark":"dracula"}}
// 好：测试实际功能
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 title="test.ts" icon="https://mintcdn.com/bun-zhcndoc/cnUTwgMuf4cCrwC-/icons/typescript.svg?fit=max&auto=format&n=cnUTwgMuf4cCrwC-&q=85&s=e7767043c9e885c34f2d6c8fe2a95217" theme={"theme":{"light":"github-light","dark":"dracula"}}
test("用户输入验证", () => {
  // 测试正常情况
  expect(validateEmail("user@example.com")).toBe(true);

  // 测试边界情况以有效提高覆盖率
  expect(validateEmail("")).toBe(false);
  expect(validateEmail("invalid")).toBe(false);
  expect(validateEmail(null)).toBe(false);
});
```

### 利用覆盖率发现缺失测试

```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
# 运行覆盖率，找出未测试代码
bun test --coverage

# 关注需要重点关注的文件
bun test --coverage src/critical-module.ts
```

### 结合其它质量指标

覆盖率只是一个指标。还应考虑：

* 代码审查质量
* 集成测试覆盖率
* 错误处理测试
* 性能测试
* 类型安全

## 常见问题排查

### 某些文件没显示覆盖率

如果某些文件未出现在覆盖率报告中，可能是测试期间没有导入这些文件。覆盖率只跟踪实际加载的文件。

```ts title="test.ts" icon="https://mintcdn.com/bun-zhcndoc/cnUTwgMuf4cCrwC-/icons/typescript.svg?fit=max&auto=format&n=cnUTwgMuf4cCrwC-&q=85&s=e7767043c9e885c34f2d6c8fe2a95217" theme={"theme":{"light":"github-light","dark":"dracula"}}
// 确保导入你想测试的模块
import { myFunction } from "../src/my-module";

test("我的函数正常工作", () => {
  expect(myFunction()).toBeDefined();
});
```

### 覆盖率报告不准确

如果看到的覆盖率报告不符合预期：

1. 检查源码映射是否正常工作
2. 检查 `coveragePathIgnorePatterns` 是否配置正确
3. 确保测试文件确实导入了要测试的代码

### 大型代码库性能问题

对于大型项目，收集覆盖率可能会导致测试变慢：

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
# 排除不需要计算覆盖率的大型目录
coveragePathIgnorePatterns = [
  "node_modules/**",
  "vendor/**",
  "generated/**"
]
```

建议仅在 CI 或特定分支运行覆盖率，而不是每次本地开发都运行。
