上一篇讲到可读性的问题。好的测试必须有好的可读性。这章接下来谈了其他好的测试的特点。
废话一样的一点,好的测试必须有好的名字,让人一眼看出测试了什么东西(这也是可读性),而且的确测试了名字所说的这样东西(这是测试的功能性)。当然命名有时候的确也是挺难的事情。
下面这个概念后面用到很多,code smell,代码异味。这是一种比喻的说法,是用来说某种不好的代码模式,人的大脑有快速识别这些模式的能力。代码虽然会有异味,但是有异味可能也是可以忍受的,不需要改动,这就是经验和艺术了。没经验的程序员的表现就是很容易纠结一些无关紧要的小Smell,对大结构的方向错误却视而不见。
作者提到一些通用的code smell是很容易识别的,比如方法太长,变量名不规范之类。对于测试代码而言,作者会特别在意测试的独立性,从反面来说,也就是说测试代码对一些其他程序组件的依赖性需要引起特别要注意,这些依赖包括: 时间,随机性,并发,基础架构(Infrastructure),预先存在的数据, 存储, 网络。
对独立性最简单的测试就是找一台干净的机器,直接从代码库中拿下代码,测试能否一下子全部跑通?一般来说,独立性越高就越可维护。还有些情况下会有这种现象,全部测试能跑通,但单个测试跑不通,这说明测试和测试之间还有依赖关系,也是很严重的独立性问题。
为解决这些问题作者随手提供了一些建议,很有价值: 1. 用测试替身(test double)代替第三方类库的依赖。 2. 测试用资源文件和代码要放在一起。 3. 让代码能自己产生所需资源。 4. 不要通过依赖其他测试来产生测试所需的上下文( context )。5. 尽量使用内存DB作为测试DB。 6. 把异步代码拆分成异步和同步两部分去测试。
面对那些不是面向测试的legacy code, 做到这些隔离是很难的。花的代价最终是否值得?我想对于一些重要的模块是值得的。
下面讨论测试的可靠性问题。测试可以分为两个极端。1. 从来不出错的测试,价值很小,可以认为什么东西也没有测。 2. 一直出错的测试,或者随机出错,也没有存在的意义。真正有用的测试需要在我们代码逻辑真的出现问题的时候告诉我们,而在没有出现问题的时候不出错。这看起来是句废话,但其实并不容易实现。
作者强调任何任务都有值得掌握的工具,我们需要至少熟练掌握一个测试框架(对java来说实际标准就是JUnit)和一个好的测试替身类库(对java而言,如Mockito, JMock)。下面作者将用一章来介绍测试替身(Test Double),下篇读书笔记详细再聊这个问题。
网友评论
名字要让人一眼看明白这个测试在测什么?应该回答的是what,而不是how。
另一个角度考虑测试名字的有效性。假想几年之后,整个工程已经有上千个测试用例了。某个新的程序员要扩充一个功能,就是你现在正在写的测试所测的。怎么保证他能找到这个测试,在现在的基础上修改。而不是干脆自己另外写一个。