智汇 IT
城启新篇

单元测试是藏在代码里的后悔药

上周三凌晨两点,微信震得我手腕麻。

是刚毕业半年的学弟,在创业公司做电商订单模块,上线前压测崩了。他哭唧唧说改了个满减的计算逻辑,改完跑了三次页面,点提交都正常,结果压测一万单直接超卖两百多。我让他把那段计算逻辑的代码贴过来,扫了三行就看到——他把满减门槛的判断写反了,本来是满三百减五十,他写成了不满三百才减。

他说之前没人要求写单元测试,大家都是写完功能点页面点两下,觉得没问题就提测。那次bug修完,他leader逼他补了所有计算逻辑的单元测试,他才发现之前还有三个藏着的边界case:比如用户有两张满减券能不能叠加,满减后金额为零的时候要不要收运费,还有跨天的订单怎么算优惠——这些东西靠手动点页面,点破头都试不完。

电商订单满减计算逻辑单元测试用例截图
电商订单满减计算逻辑单元测试用例截图

没人敢删代码的团队,迟早被代码压垮

我见过太多团队,把单元测试当成应付检查的差事。为了凑够要求的覆盖率,连只有一行get方法的实体类都要写测试,跑出来的报告绿油油一片,说出去都没人信,真出了bug啥用都没有。

更有意思的是,很多新人刚进团队,看着积年累月堆出来的代码,连注释都没有,改个变量名都要提心吊胆,生怕碰坏了哪个藏在角落里的逻辑。为啥?就是因为没人给这些老代码写测试。你连这个函数改完之后会影响哪些流程都不知道,谁敢动?

上次帮一个朋友的团队排查老系统的问题,他们的用户权限模块已经跑了五年,中间换了七波开发,没人敢动里面的核心判断逻辑。最后他们花了两周时间,把权限判断的核心逻辑补了二十多个测试用例,才敢下手优化。原来之前大家不敢动的原因,是怕改完之后,有的用户能看到不属于自己的订单,这种问题真出了,谁都担不起责任。

能救命的测试,从来不是凑数的覆盖率

很多人对单元测试的误解,就是觉得要把所有代码都覆盖到。真不是。

我自己写代码这么多年,觉得最有价值的测试,从来不是测那些一眼就能看出来对错的逻辑,是测那些你上次出过bug的地方,测那些和钱、权限、用户核心数据相关的逻辑。

就像那个学弟后来补的测试,他没有给所有的订单方法都写测试,就盯着满减计算、优惠券叠加、运费规则这三个最容易出问题的地方,写了二十多个用例。后来他改了个优惠券叠加的规则,刚点完保存,跑测试就直接报红——原来他改的时候不小心把满减门槛的判断逻辑给覆盖了。要是没这个测试,指不定又要等到上线后超卖才发现。

IDE中运行单元测试报错的界面截图
IDE中运行单元测试报错的界面截图

我刚工作那会也傻,觉得写测试是浪费时间。直到有次改支付回调的逻辑,没写测试,上线后凌晨三点被运维的电话炸醒,说一百多笔订单的回调状态错了,用户付了钱还是显示待支付。那天我蹲在公司走廊啃着凉包子改bug,改到天亮的时候就发誓,以后但凡涉及钱的逻辑,绝对要把单元测试写全。

真的,你写测试花的那十几分钟,省下来的可能是你熬一整夜的时间,还有被用户投诉的麻烦。

不用追求完美,先把最痛的地方测起来

别一上来就喊着要整个团队覆盖率到90%,那纯粹是给自己找不痛快。

先从你上次出bug最多的模块开始。比如每次上线都要出问题的订单计算,比如经常漏权限的用户校验,这些地方先把核心逻辑的测试写了。哪怕每次只写两三个用例,攒个半年,你回头看,整个模块的稳定性都会上一个台阶。

别写没用的测试。比如你写了个把字符串转成大写的工具函数,测个正常场景就够了,别没事测空字符串、测超长字符串、测带特殊字符的字符串——除非这个工具函数真的处理过这些特殊情况,不然写了也是白写。

写测试的时候要像个会找茬的用户。别总是传正常的参数,要传那些你觉得’正常人不会这么用’的参数。比如用户输入的金额是负数?比如订单的商品数量是零?比如优惠券的有效期已经过了三天?这些看起来离谱的场景,真的会有用户触发的。

我现在写代码的习惯是,写完一段核心逻辑,先花五分钟把最容易错的几个边界case测了,再往下写。刚开始的时候觉得慢,等写个三五次就会发现,你写代码的时候会自动把逻辑拆得更清楚——毕竟你要是把所有逻辑都揉在一个两百行的函数里,你自己都不知道怎么写测试。

上周学弟给我发消息,说他们现在团队每次上线前都会跑一遍核心模块的单元测试,最近三个月都没出过线上的逻辑bug。他说以前觉得写测试是浪费时间,现在才发现,那些花在写测试上的时间,最后都会变成你凌晨可以安稳睡觉的底气。

免责声明:市场有风险,选择需谨慎!此文仅供参考,不作买卖依据。如有侵权请联系删除。
文章名称:单元测试是藏在代码里的后悔药
文章链接:https://www.itcdj.com/it/349.html