上周三凌晨两点十七分,手机的企业微信告警震得我枕头都掉在地上。是去年刚入职的小周写的优惠券结算模块,满减叠加的分支判断漏了一个临界值,三个用户的实付金额少算了八毛六,平台直接触发了资金异常告警。爬起来远程改代码的那半小时,我盯着满屏的if else,突然想起三年前自己刚当开发的时候,也是觉得单元测试是耽误干活的累赘——写完功能跑通主流程就扔测试环境,哪管什么边界值。
大家对单元测试的偏见是怎么来的
说真的,大部分开发抵触单元测试,真不是懒。是被那些形式主义的要求搞怕了。
之前在一个互联网小厂待过,领导一拍脑袋要求全项目行覆盖率冲到80%,不然绩效打C。大家为了凑数,写的测试用例全是走过场:调用核心函数传个最正常的参数,判断返回值是不是预期的正确结果,异常分支、边界值一个不碰。

这种测试写了有什么用?每次跑测试套件要花整整三分钟,改个函数名还要连带改十几处测试用例,纯纯给自己找事。时间长了,大家自然觉得单元测试就是个没用的KPI,是领导拍脑袋想出来折腾人的东西。
更离谱的是,很多团队推单元测试的时候,根本不分场景。写个静态的活动落地页,连个业务判断都没有,也要求写测试测“组件渲染是不是正常”;写个纯展示的列表页,也要求测“接口返回空的时候页面会不会崩”。这种没有实际业务价值的测试,写得越多,大家的抵触情绪越大。
真的能帮你少熬夜的单元测试长什么样
我后来真正认可单元测试的价值,是在那次用户等级掉分的事故之后。
当时我负责用户成长体系的模块,改完等级计算的逻辑上线,有个老用户的等级从V3直接掉到了V1,打了12315投诉。查了半天才发现,是判断等级的时候漏了一个“累计消费满1000自动升V3”的分支,改代码的时候把这行判断给删了。要是当时有对应的单元测试,改完跑一遍用例十秒钟就能发现问题,根本不会闹到要投诉的地步。
真的疼。
后来我们给核心模块补测试的时候,根本没追求什么覆盖率数字,就盯着几个最容易出问题的核心场景写:满减门槛刚好卡线的时候算不算,两个同类型满减能不能叠加,用户输入的金额是负数的时候怎么兜底,等级计算的时候漏了某个分支会不会触发降级。

单元测试从来不是给测试人员写的,是给半年后要改这段代码的你自己写的。
我之前算过一笔账,给核心业务逻辑写一套覆盖所有分支的单元测试,大概要花两三个小时。但是每次改代码的时候,能省下来的排查、提测、和测试同学扯皮的时间,远不止这个数。上次我们调整优惠券的优先级规则,改完跑了一遍所有的单元测试用例,十秒钟就发现之前的满减卡线场景出问题了。要是按照以前的流程,改完扔测试环境,测试同学点半天才能碰到那个临界值,再提bug回来改,一来一回至少两小时,搞不好就带到线上去了。
太爽了。
算下来血赚。
别为了写测试而写测试
不过话说回来,很多人一提到单元测试就觉得要占用大量开发时间,其实根本不是。
现在我所在的团队,从来不会给大家定什么强制的覆盖率指标。我们的规则很简单:涉及资金计算、用户权益、核心流程的代码,分支覆盖率必须到90%以上;纯页面展示、简单工具函数的代码,主流程能跑通就行,写不写测试全看开发自己的习惯。
之前见过走火入魔的团队,为了凑100%的覆盖率,连日志打印的代码行都要写个测试用例,测“日志是不是真的打印出来了”。这种操作纯纯是把单元测试的初衷搞反了。
要是你现在还没开始写单元测试,不用上来就给自己定个宏大的目标。下次写核心逻辑的时候,多花十分钟,把你能想到的所有可能出错的边界值列出来,对着写三个测试用例就行。
别贪多。
等你下次上线的时候,不用在凌晨被告警喊起来改bug,不用对着线上的异常日志翻半小时之前的代码,你就知道这十分钟花得有多值。