上线前跑完单元测试,覆盖率报告弹出个刺眼的 62% —— 团队群里瞬间安静了。产品经理在问‘能上线吗’,测试同学在翻日志,开发蹲在工位上盯着 IDE 里那几块灰色未覆盖的代码发呆。
先别急着补 test,看看是不是‘假低’
很多团队一看到数字没到 80% 就开干,结果补了一堆空壳测试:调用一下方法、断言个 true、mock 全家桶走一遍……覆盖率涨到了 85%,但线上照样崩。这种‘刷分式覆盖’毫无意义。打开你的覆盖率报告(比如 Istanbul 或 JaCoCo),点进去看具体哪几行没走——是 if 分支里的兜底逻辑?是 catch 块里一行 logger.error?还是压根没人调用的旧接口?如果是后者,删掉比写测试更健康。
从‘高价值路径’开始补,不是从‘文件列表’开始补
别打开 src/ 目录,挨个右键 ‘Generate Test’。试试这样:打开最近一次线上告警的链路追踪,挑出被频繁调用且参与核心计算的 3 个函数;或者翻 Git 提交记录,找过去两周改动最多、评审 comments 最多的那几个类。优先给它们补带真实输入输出的测试。比如订单创建服务里,calculateDiscount() 方法被 7 个地方调用,但只有 1 行测试用例,那就先加边界值(满减门槛刚好卡住、优惠券过期、用户等级为 0)和异常流(传入 null 价格)。跑一遍,覆盖率可能只涨 2%,但防御力实打实上去了。
接受‘合理缺口’,把精力留给真正要命的地方
有些代码天生难测:React 组件里纯 UI 渲染逻辑(比如 <div className={theme === 'dark' ? 'bg-gray-900' : 'bg-white'}>)、Spring Boot 的 @ConfigurationProperties 绑定类、甚至一段手动写的 JSON 序列化工具方法。只要它不包含业务判断、不读写外部状态、不抛异常,覆盖率低点真没关系。把时间省下来,去给支付回调验签、库存扣减幂等、分布式事务补偿这些地方写集成测试,效果远胜于给 20 个 getter 补 assert。
覆盖率是镜子,不是尺子。照出问题才重要,量出数字只是第一步。