工作了快 10 年了,跟研发小伙伴聊起单测,绝大多数人的反应是 —— 单测没啥用,写单测就是为了应付单测覆盖率的 KPI 指标。恰好我最近在团队落地单测相关的内容,经过一段时间的持续迭代,我对单测的看法也从一开始的 没啥用
到后面的 好像有点东西
,再到最后的 卧槽,真牛逼!
。基本上随着单测写得越深入,我对单测就越发重视。
为啥说单测没啥用?
那些说单测没啥用的小伙伴,我想大概率是不知道怎么写单测,没写过真正合格的单测,而只是用单测来凑凑单测覆盖率的 KPI 指标。在这种情况下,单测当然没啥用,因为它没办法帮你提高代码质量,帮你减少 bug。试想一下,如果一个东西能帮你提升需求开发质量,减少提测需求 bug 数量,那研发同学怎么可能不愿意去学习一下呢?
在我看来,单测一个很明显的价值就是 —— 它能极大地减少你的需求 bug 数量,甚至一个 bug 都没有! 那为啥大家都会觉得单测没用呢?我想问题可能是多方面的,其中可能的几个原因是:
- 需求不明确,边写代码边改需求,这咋写单测?
- 时间非常赶,业务代码都写不完,还写单测?
- 不知道咋写单测,于是随便写写,发现好像没啥用?
- 没有选择合适的单测框架,单测代码写得业务代码还多,这可咋整?
- 等等
总而言之,这一切的原因导致没写出合格的单测,没办法让单测为他们带来好处,于是它们对单测充满了失望,最终就觉得单测没用。那怎么写出合格的单测呢?这就是另外一个话题了,有机会我们再详细聊聊。
单测到底有啥用?
听我瞎扯了半天,有同学忍不住了:看你把单测吹得,那你说单测到底有啥用?
在我看来,单测除了显著提升需求代码质量之外,还有下面几个好处:
- 提升系统稳定性
- 系统更加健壮
- 提升代码编写能力
- 有利于稳定迭代
- 有利于深入了解技术与业务
提升系统稳定性。 如果你每一个方法函数都经过了测试,并且其分支覆盖率都达到了较高水平,那么你很难写出有问题的代码,因为每种情况你都考虑到了。而在后续的迭代中,由于单测用例的存在,它就可以保证修改后的代码不会影响到之前的业务逻辑。简单来说,由于单测的存在,违背之前业务逻辑的代码无法运行通过,因此提高了系统稳定性。
系统更加健壮。 系统的健壮,其实是得通过分支覆盖率来实现的。分支覆盖率,其实就是每一种可能的情况你都考虑到了,那么系统会更加健壮。举一个很简单的例子,有一个计算器类的除法函数,简单的测试可能只会用正数进行测试,更进一步地可能会用负数,但是如果用 0 去测试呢?是否能成功呢?通过对分支覆盖率的要求,使得我们考虑到更多异常情况,从而使得系统更加健壮。
提升代码编写能力。 当我们开始对单测覆盖率和分支覆盖率有要求,并且开始写单测代码之后,我们会被迫站在另一个视角去审视我们写的代码。如果我们的代码写得一点逻辑都没有,那我们的单测会很难写,那我们会忍不住去重写它,这就间接地提升了我们的代码编写能力。与代码逻辑类似,代码的结构以及设计也会影响单测的编写,写单测可以让我们重新审视自己写得代码,从而间接提升我们的代码编写能力。
有利于稳定迭代。 如果你写得代码质量很高,只有非常少的 bug,甚至一个 bug 都没有。那么测你需求的测试肯定很开心,因为直接一把过呀!从项目管理层面来看,如果每个人都能做到这样的程度,那么项目的迭代是非常稳定、并且高效的!
有利于深入了解技术与业务。 当我们写单测的时候,我们必须去了解某个东西是怎么运行的。如果你没有了解清楚某块业务,就开始去修改这块业务的代码,那之前的单测用例会教你做人,频频报错的单测信息会让你寸步难行。单测用例的存在让你必须弄清楚这块业务的逻辑,才可以写新的业务逻辑,这间接促进了我们对于业务的了解。此外,我们写单测的时候经常会进行 Stub 和 Mock,这会要求你必须弄清楚项目中用到的技术原理,不然你无法成功编写单测代码,这也同样间接促进你去了解项目中用到的技术。
单测不是银弹
说了这么多,可能有些小伙伴觉得我是单测的死忠粉。但我想说的是:单测也不是银弹!
在我看来,单测只能解决一类问题,那就是 —— 你觉得你写对了,但是你没写对的问题。 对于那些你本来就不知道,或者说代码里根本就没写的东西,单测是无能为力的。举个很简单的几个例子:
- 提测提了一个 bug,你排查之后发现有某个业务细节你没考虑到,从而触发了这个 bug。由于你本来就没考虑到,因此代码里也没有做对应的处理,那么单测肯定也解决不了这个问题。
- 由于产品对需求没有写清楚,于是在测试解决不断补需求细节,于是你也不断地修修改改,于是越改 bug 越多。
除此之外,写单测也确实是会费一些时间,特别是对于刚刚写单测的同学来说。如果一个项目非常紧张,需求也不确定,经常边写代码边该需求,这时候再要求单测覆盖率,可能不太现实。
单测的适用场景
看了这么多,知道了单测有那么多好处,但又单测又不能包治百病,那单测到底适合在什么场景使用呢?
在我看来,对于是否要推行单测,以及单测的要求高低,其实取决于下面几个维度:
- 1. 代码复用率。 代码复用率越高,越有必要推行单测,越有必要提升单测的要求。因此这些代码被很多业务引用,因此其一旦有问题便会影响很多业务方,在这样的代码推行单测是收益较高的。
- 业务变化率。 业务变化越快,越不适合用单测。如果业务变化非常快,一个单测的内容上线了没几天就又要修改,那么你不仅仅需要修改业务代码,还需要修改单测代码,那就是双倍的工作量了。
- 人员变化率。 人员变化率指的是某个模块负责人的变化情况。如果某个模块的负责人经常变来变去,那么也是不太适合推行单测的。因为新负责的人需要花大量的时间去熟悉单测的内容,这会导致需求开发的时间变得非常长。
- 业务重要性。 越是核心的业务,越有必要推行单测,并且越有必要以高标准要求。因为核心业务的稳定性、健壮性对于公司来说肯定非常重要,而单测确实是能够在最小单元去提升系统稳定性和系统健壮性。
上面提到的 4 个衡量维度,我们不能单一地去看待,而是要根据实际情况去综合判断。例如某个业务的人员变化就是很频繁,那就一定不适合推行单测吗?其实并不是,而是说对于人员变化非常频繁的业务,其推行单测成本会很高。但如果这块业务就是非常重要,但他的人员变化就是很频繁,那强制以高标准的单测要求确实可以提高系统健壮性和系统稳定性,但是代价就是研发时间很长。如果产研团队能够接受这个结果,那么这么做就是合理的。
总的来看,是否推行单测以及推行单测的标准高低,需要我们根据上面几个维度去综合考量,得出一个最适合的标准!