最近在开发公司的集成测试框架,有一些关于单元测试的体会,写一个博客记录一下想法。

为什么要写单元测试?

这个问题,已经有无数的关于技术的书、文章去阐述了,不断地强调单元测试的重要性。比如单元测试可以让你在软件开发的早期阶段发现 Bug,而不必到集成测试的时候才发现等等。不过,对于我来说,在切实地戳到我的痛点之前,我一直都没有去重视这些关于单元测试的忠告(虽然在心中记着,但是实际上并不是很在意)。

在写公司的集成测试框架的时候,有那么好几次,在调整了现有的功能,或者修复了某个 Bug 之后,因为懒惰,也因为跑一次完整的单元测试所需要的耗时较长,我侥幸地认为这些修改应该没有问题,直接打包交付。结果是,墨菲定律出现了,果然,没有经过测试的修改引发了新的 Bug,我不得不重新修改代码,然后厚着脸皮让用户重新试一次。

人总是不靠谱的,我们懒惰,我们存在侥幸心理,坏事儿总是在我们最不希望发生的时候发生。写单元测试不能防止我们懒惰,防止我们存在侥幸心理。但是一次成本低廉的单元测试会让我们觉得:“反正运行一次但单元测试不会耗费很多时间,不如跑一次吧”,它在一定程度上降低我们犯错的几率。

单元测试对于重构的意义也非常重大。很多有意思的程序员都有洁癖,会想着去修改某一段「恶心」的代码。我有过这样几次经历,在把一段「恶心」的代码修改地赏心悦目后,最后上线后发现引入了一个 Bug,心里暗骂一句 WTF,然后一脸黑线地把 Bug 修改了,想想如果当时有单元测试,那么会给我多大的勇气,让我可以肆无忌惮地去重构代码,这是多么爽的一件事情。

好的单元测试应该是怎样的?

一个好的单元测试,我觉得最重要的一点就是运行成本得低,也就是说一个单元测试越快越好。运行一次单元测试的成本越低,你才会越愿意去运行单元测试。如果运行一次单元测试得 10 分钟 20 分钟,那么我想很多人的侥幸心理又会出来了。

我是怎样写单元测试的?

我一般是这样写单元测试的,先想清楚模块的边界,有哪几种可能的输入,这些输入对应的可能输出是什么,然后以最快的速度堆积代码把功能先实现出来,接着写单元测试,把测试用例全部跑过。接下来马上着手重构之前写的代码,不断重构,不断地跑单元测试,知道重构后的代码让自己满意为止。