什么才是“好的”代码覆盖率?我在现实世界里用来挡住 bug、又不浪费工程时间的指南
每次我运行 npm run coverage 或 phpunit --coverage,同一个问题都会冒出来:
“好吧……74 %。够了吗?”
软件开发博客圈喊着 "100 % or nothing!" 与此同时,launchdarkly.com 很礼貌地提醒我:100 % executed ≠ 100 % tested。 我花过几个星期追逐这个闪亮指标,也花过更多星期调试_别的_问题。下面是我最后落脚的、经过现场验证的中间地带。
为什么 100 % 覆盖率是一场海市蜃楼
理论上,100 % 行执行意味着"没有隐藏 bug"。实践中:
- 收益递减:从 90 %→95 % 常常会让测试套件翻倍,却只带来个位数的风险降低。
- 虚假的信心:一个没有 assertion、只是调用函数的测试,仍然算覆盖。
- 商业现实:每多写一个测试,就是一段没有用在客户要求功能上的时间。
航空航天那帮人可以瞄准 100 %,那是生死问题。对我们其他人来说,~80 % 是 80/20 线。大多数项目在算过 ROI 后都会聚在这里。testdevlab.com 出于同样的原因,把范围称为 70–90 %。
我使用的实用表格
| Coverage | 我的翻译 | Action |
|---|---|---|
| 100 % | “我们是一个会飞火箭的 library” | 接受折磨。 |
| 90 % + | “很多钱都依赖它的 library” | 只用于高优先级模块。 |
| 80 % | 发出去,监控,然后迭代。 | |
| 60–70 % | Merge gate——如果新代码把你拉到线下,就让 PR 失败。 | |
| < 50 % | 一个周末的技术债——先转向关键路径。 |
这些数字我从 Atlassian 的内部指南 偷来的:60 % 是 "acceptable",75 % 是 "commendable",90 % 是 "exemplary"。每次 retro 都好用。
我如何不哭着打到 80 %(TypeScript playbook)
- Jest + Istanbul 开箱即用
- CI 中的 coverage gate
在
jest.config.js里我会加:coverageThreshold: { global: 80, '**/src/core/**': 90 } - 盯住用户热路径,不要盯 Redux boilerplate logger。
我如何在 Laravel 中打到 80 %(PHP playbook)
- 开发环境安装 PCOV 提速度,CI 中用 Xdebug 拿 branch data。
- PHPUnit +
phpunit.xml中这些默认项:<filter> <whitelist processUncoveredFiles="true"> <directory suffix=".php">./src</directory> </whitelist> </filter> - Mutation score > line count,使用 Infection。这就是我发现"覆盖了但其实没测到"的行的方法。
我团队奉行的 4 条规则
- 新代码 = 测试。 合并前 diff coverage ≥ 90 %。
- 先重构,再测试。 不可测试的代码已经是债。
- 让 build 失败,不要让人失败。 每年把 gate 降低 5 %,也比用一片红色 dashboard 压垮团队好。
- 衡量生产环境里的 bug——如果覆盖率是 85 %,但 incident 激增,罪魁祸首不是覆盖率,而是断言。
TL;DR(给 execs 和 recruiters 也一样)
别问我要一个"神奇数字"。问这个:
产品的哪些部分不能坏?
把那些覆盖到 90 %。其他部分给健康的 smoke tests。把代码覆盖率当作一束聚光灯,不是终点线;相信你抓到的 bug,不要相信你炫耀的数字。
让 coverage dashboard 变绿吧。你的客户永远不会看见它,但他们的 error bar 会保持空白。
—— 吐槽结束,回编辑器。

评论