覆盖率是重构导航仪:①分支覆盖防else遗漏;②行覆盖保return/throw/early exit;③函数覆盖守工具方法;④聚焦高复杂度低覆盖模块优先重构。

写 JS 代码覆盖率与重构指南,核心不是堆砌工具命令,而是把“测得到”和“改得稳”真正串起来。重点在于让覆盖率成为重构的导航仪,而不是交差报表。
明确覆盖率指标的实际意义
别只盯着百分比数字。JS 项目中真正影响重构安全的是这三类覆盖:
- 分支覆盖率:if/else、switch/case、三元表达式每条路径都得有测试对应。重构时漏掉一个 else 分支,就可能线上报错。
- 行覆盖率:尤其关注 return 语句、throw 抛错、early exit(如 guard clause)这些单行逻辑——它们常被忽略,但一出问题就是阻断性故障。
- 函数覆盖率:对工具函数、工具类方法(如 formatCurrency、deepClone)必须 100% 覆盖,它们被多处调用,一处失效影响面广。
用覆盖率驱动重构节奏
把覆盖率报告当作待办清单,而不是验收门槛:
- 运行
npm test -- --coverage后,打开coverage/lcov-report/index.html,直接点击低覆盖文件。 - 优先重构“高复杂度 + 低覆盖”模块(比如圈复杂度 > 8 且分支覆盖率
- 对未覆盖行加注释标记:
// TODO: cover this path in test — e.g. when user.role === 'guest',让测试补全目标具体可感。
重构前先加固测试层
没有可靠测试就动手重构,等于蒙眼拆电路。三步快速筑网:
-
补边界用例:对参数校验逻辑(如
if (val == null)、Array.isArray())补充 null、undefined、空数组、非数组等输入。 -
抓异步盲区:Promise reject、fetch 失败、timeout 场景必须显式测试,Jest 中用
await expect(...).rejects.toThrow()或jest.mock('node-fetch')控制响应。 - 隔离副作用:将 localStorage、Date.now()、Math.random() 等外部依赖抽成可注入函数,测试时传入可控桩(stub),避免覆盖率统计失真。
重构后验证覆盖率不退化
每次提交前加一道轻量检查:
- 在 CI 脚本里加入阈值校验:
nyc check-coverage --statements 85 --branches 75 --functions 85,不达标直接失败。 - 对关键模块(如支付、权限、数据解析)单独设更高阈值,例如
src/utils/parser.js要求分支 100%,并在 jest.config.js 的collectCoverageFrom中单独配置路径。 - 用
// istanbul ignore next只屏蔽真正无法测试的代码(如仅在 IE9 运行的 polyfill),禁止用于跳过业务逻辑。











