代码覆盖率与静态检查是互补的质量维度,需在ci中联动设门禁:eslint过滤伪覆盖、暴露未触发路径,覆盖率验证静态规则遗漏问题,并通过报告联动实现精准修复。

代码覆盖率和静态检查不是并列的两件事,而是互补的两个质量维度:覆盖率告诉你“哪些代码被运行过”,静态检查告诉你“哪些代码写得不对”。真正提升质量,得让它们在同一个流程里互相校验、彼此补位。
用静态检查过滤低价值覆盖
高覆盖率可能掩盖大量无效测试。比如一个空的 if (true) { } 被测了,语句和分支都算覆盖,但毫无业务意义。ESLint 配合 no-constant-condition 或 no-unused-expressions 规则,能提前标出这类“伪覆盖”语句。发现后直接删掉对应测试或重构逻辑,避免把覆盖率数字刷上去却没增强健壮性。
- 在 .eslintrc.js 中启用 eslint-plugin-testing-library,自动提示“只断言渲染、不验证行为”的测试写法
- 对 Jest 测试文件单独启用 jest/no-identical-title 和 jest/no-disabled-tests,防止测试失效却仍计入覆盖率
- 用 typescript-eslint 的 no-unused-vars 检查测试中声明但未使用的 mock 变量——它往往意味着该路径根本没走通
让覆盖率暴露静态规则漏掉的问题
有些问题静态工具无法判断,必须靠执行路径触发。比如一个 try/catch 块里调用了外部 SDK,ESLint 看不出这个 catch 是否真会被执行;但覆盖率报告里如果该 catch 分支标红,就说明异常路径完全没测。这时再回看 ESLint 是否启用了 no-empty(禁止空 catch),如果没有,就补上;如果有却被绕过了,说明测试设计有缺口,要补异常模拟。
- 对所有标红的 throw 语句,检查是否被 expect(fn).toThrow() 覆盖;没覆盖就补,覆盖了但 ESLint 报 no-unsafe-finally 就优化清理逻辑
- 若某函数在覆盖率中未调用,但 ESLint 显示它被导出且无未使用警告,说明它是“存在但不可达”——可能是路由配置错误、事件绑定遗漏,需人工排查上下文
- 分支覆盖率低的文件,配合 sonarjs 扫描圈复杂度。若某 if 嵌套过深(如 >5),ESLint 的 complexity 规则会报警,而覆盖率能确认这些深层分支是否真实触发
在 CI 流程里设双门槛,不达标就卡住
不要只设一个覆盖率阈值。把静态检查和覆盖率组合成门禁条件,才能守住质量底线。
- GitHub Actions 中先跑 npx eslint . --ext .js,.ts,失败直接退出;通过后再跑 npx jest --coverage
- 在 jest.config.js 里配置:coverageThreshold: { global: { branches: 80, functions: 85 } };同时要求 ESLint 错误数为 0,警告数 ≤3(可配 --max-warnings 3)
- 对核心模块(如权限校验、支付回调),额外加一条检查:if coverage for src/utils/auth.ts
报告联动:从红字定位到修复建议
别分开看两份报告。用 Istanbul 生成 HTML 覆盖率报告时,点击标红语句,旁边可以嵌入 ESLint 对该行的检查结果(需自定义 reporter 或用 eslint-istanbul 插件)。例如某行 res.status(200).json(data) 标红,ESLint 同时报 no-res-json(禁止直接用 json 方法),那就清楚知道:这不是漏测,是逻辑不该这么写——删代码比补测试更有效。
- 用 eslint-plugin-jest 检查测试本身的质量,比如是否用了 test.only、mock 是否覆盖全部依赖
- 对 Prettier 格式问题,不阻断 CI,但要求覆盖率报告中“未格式化文件”的分支覆盖率必须 ≥90%,倒逼开发者先格式化再提交
- 当某文件 ESLint 无报错但分支覆盖率低于 60%,自动在 PR 评论里贴出该文件 top 3 未覆盖分支,并附上对应业务场景提示(如“缺少 status=‘pending’ 时的处理”)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











