Skip to content
返回质量保障

覆盖率策略

把覆盖率当未测风险地图,非最大化的百分比。

为什么

覆盖率是测试中最被误解的指标。100% 行覆盖不意味 100% 测试过——它意味每行至少执行一次,非每行被断言。零断言 100% 覆盖套件全绿守卫啥也不。覆盖率价值不在数字;在它产的图:业务逻辑中未覆盖分支是 bug 可藏不被抓处。当风险地图用,覆盖率指导下一条测试写哪。当目标用,它激励平凡测试涨计数而不验行为,数字变谎言。

何时使用

每次 CI 运行生成覆盖率报告,写新代码或规划测试冲刺时审查。不要用覆盖率阈值门控合并——门控新代码未覆盖分支是否在业务逻辑(须覆盖)还是平凡代码(可接受)。

如何做

1. 在测试运行器配覆盖率收集
   - Vitest: coverage: { provider: "v8", reporter: ["text", "html", "lcov"] }
   - 仅含 src/(业务逻辑),排除 tests/、配置、入口点
   - 用分支覆盖非仅行覆盖——分支抓 if/else 缺口

2. 生成报告读 HTML 视图
   - 开 coverage/index.html——红行未覆盖,黄行部分分支
   - 聚焦业务逻辑文件(src/lib、src/services),非配置或 UI 壳
   - 记具体未覆盖分支,非仅百分比

3. 分类每个未覆盖分支
   - "须覆盖"——业务逻辑、错误处理、边界条件 → 写测试
   - "应覆盖"——较不关键但仍逻辑 → 有时间写
   - "可接受"——平凡 getter、框架样板、仅错误日志 → 跳过

4. 为"须覆盖"分支写测试,非为涨百分比
   - 目标是消除风险非涨计数
   - 覆盖分支但不断言的测试无价值——验证行为

5. 追踪覆盖率趋势,非绝对数
   - 变更文件覆盖下降是有人跳测试的信号
   - 平凡测试填充的上涨非改善——看变异分数

示例

// vitest.config.ts
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    coverage: {
      provider: "v8",
      reporter: ["text", "html", "lcov"],
      include: ["src/lib/**", "src/services/**"],  // 仅业务逻辑
      exclude: ["**/*.config.*", "**/index.ts", "**/*.test.ts"],
      branches: 100,  // 报告所有未覆盖分支
      lines: 80,      // 业务逻辑行覆盖 < 80% 警告
    },
  },
});

// 测试运行后开 coverage/index.html:
// src/lib/discount.ts        — 100% 行,75% 分支(SAVE20 的 else 未测)
// src/lib/pricing.ts         — 60% 行(批量折扣分支从未执行)
// src/services/checkout.ts   — 90% 行,50% 分支(错误路径未测)
//
// 行动: 为 checkout.ts 错误路径和 pricing.ts 批量折扣写测试。
// 别为 discount.ts 凑 100%——未覆盖分支是平凡 else-return,
// 测试只增噪声不抓 bug。

常见问题

  • ⚠对每个文件设硬 80% 覆盖门控激励开发者为样板代码(getter、框架钩子)写平凡测试只为过门控,增噪声不减风险。
  • ⚠仅报行覆盖藏最重要缺口——每行都跑但 if 和 else 分支从未都执行的函数有 100% 行覆盖 50% 分支覆盖。
  • ⚠追全仓 100% 覆盖(含配置、入口点、类型定义)浪费在无法有意义测试的代码上,稀释对业务逻辑的聚焦。
  • ⚠把覆盖率当唯一质量指标导致高覆盖低断言质量套件——数字好看,套件啥也不抓,到生产才发觉。

最佳实践

  • ✓把覆盖限定到业务逻辑(src/lib、src/services)排除配置、入口点、类型定义——要紧的数字是能有 bug 代码的覆盖。
  • ✓用分支覆盖作主指标非行覆盖——分支揭示 if/else 和 switch 缺口,边界 bug 藏处,行覆盖藏它们。
  • ✓把未覆盖分支报告当风险地图审查:业务逻辑中每个红分支是 bug 可藏处,下一条测试应瞄准最高风险红分支。
  • ✓覆盖率配变异测试得真质量信号——覆盖说"这行跑了",变异说"若这行错测试会发觉",只有后者意味测过。