Kevlin Hnney是英国的一位独立顾问和培训师,其关注的范围主要包括软件架构、模式、开发过程和程序设计语言。在本文中他将谈谈如何通过单元测试提高开发效率。
单元测试只会浪费时间吗?某些软件专家们确实是这么想的。最近在Software Quality Insights上看到一篇文章——《单元测试真的有用吗?》。那些认为单元测试无用的开发人员给出了如下理由:
1. 他们不了解单元测试。
2. 很难写出优秀的单元测试。
3. 单元测试只会浪费时间、降低效率。
4. 写单元测试需要太多时间(特别是频繁的迭代开发)。
5. 回归测试更有效率。
本文将重点讨论后面三个问题,即单元测试与开发效率的关系。
效率 vs 人员安排
单元测试会降低效率、造成时间上的浪费吗?这取决于所说的效率是什么,以及所说的时间对象是谁。在一个纯粹编写新代码的周期里,写单元测试的程序员所写代码可能会比不写单元测试的少。如果所说的效率是指这个,那么单元测试确实会降低程序员的效率。
但是,我们很容易发现这种牵强的效率定义的问题所在。代码行并不是衡量效率的标准,它只是所写代码的行数。从单个类到整个系统,我们可以发现很多代码行数已经远超出了实际所需。
我们需要的并不是更多的代码,而是准确的代码。单元测试可以让我们随时进行代码层次上的真实性检查,它可以告诉我们是否在开发正确的东西。所以越多的测试就意味着越少的代码。这并不是什么坏事。开发速率(development velocity)与开发速度(development speed)的区别就在于方向。向正确的方向前进即使几步也要好于在错误的方向上飞奔。
另一个错误的想法是开发人员大部分时间都在编写新代码。虽然开发人员也想专心于代码,但是现实却并非如此。会议(与团队、管理人员、客户、投资商等)、邮件、程序调试、会话、文档制作、安装、研究评估、帮助解决问题、跟进支持、合并版本、处理配置管理系统等都是需要考虑的。
虽然各部分所占比例根据项目与公司的不同而有所变化,但是这些都是与代码无关的活动,而且所占时间总和要高于编写代码占用的时间。问题在于,如果我们把一部分编码时间用于单元测试,那么上面这些时间有多少可以转化为编码时间呢?
局部优化 vs 全局优化
看清全局也很重要。下面Alfred Aho说所的关于开发AWK语言的故事颇有一些值得我们考虑的地方:
“如果再有这样一次机会,我们在开发这种语言的时候肯定会增加严格的测试。我们当时是把AWK当作一种”临时性(throw-away)“语言进行开发,所以并没有考虑严格的质量控制……曾经有个人用AWK编写了一个CAD系统。他来找我,想告诉我AWK编译器的一个Bug。他很生气,说我浪费了他三个星期的生命,因为他用了三个星期查找他代码里的错误,结果却发现是编译器的问题!后来我和Brian Kernighan讨论过这个问题,我们觉得应该做一些质量控制方面的工作。然后,我们针对AWK所有功能做了一次严格的回归测试。从那以后,我们三人无论谁为这种语言增加新功能的时候,都要先写一份相应的测试。”
这个故事的意义就在于它是比较早的拥护“测试先行”编程方式的实例——在实现某个功能之前先把测试写出来,而不是只在计划或者口头说说。另外,这个故事也说明了如何把短期、临时性或针对性代码转变为长期、稳定的方案。