第一章 优秀测试的承诺
本章内容包括:
●编写单元测试的价值
●测试如何提高程序员的生产力
●将测试用作设计工具
当我开始吃上编程这碗饭时,世界看起来与今日大不一样。那是10多年以前,人们使用着简单的Vim和Emacs等文本编辑器,而非如今的Eclipse、NetBeans和IDEA等集成开发环境。我清楚地记得,某位资深同事在调试软件时摆弄着Emacs宏,生成大量的System.out.println调用。我甚至还清楚地记得,当一个主要客户报告说他们的订单没有正常生成时,我们要把打印出的日志破译出来。
那时候,“测试”对大多数程序员来说意味着下面两件事之一要么是由专人在自已完成编码之后所做的事情,要么是在声称编码完成之前对代码所捣鼓的事情。当引人一个Bug后,你会再次对自己的代码动手折腾番这次要增加一些日志,看看能否找出错误之处。
自动化曾是我们最先进的概念。我们用makefiles来重复地编译和打包代码,但尚未将运行自动化测试作为构建的一部分。我们曾用各种shell脚本来启动一两个“测试类”一操作生产代码的小程序,用来打印发生了什么,以及对于某些输人,代码的输出是什么。我们完全没有任何标准的测试框架,也没有自验证( self-verifying)的测试可以用来报告断言中的各种失败。
我们走过了漫长的日子,好不容易才到今天。
1.1国情咨文:编写更好的测试
下述概念如今已被广泛推荐,即开发者应该编写自动化测试,以便当发现回归问题时就使构建失败。而且,测试先行的编程风格已有大量的专业研究,使用自动化测试不仅是保护回归,而且是帮助设计,在编写代码之前就指出代码的期望行为,从而在验证实现之前先验证设计。
作为顾问,我见过很多团队、组织、产品和代码。看看今天的我们,很明显自动化测试已经成为主流。这很棒,因为没有自动化测试,大多数软件项目会比现在更糟。自动化测试改善了你的生产力,使你获得并保持开发速度。
救命!我是单元测试新手
如果你还不熟悉如何编写自动化测试,现如今是一个熟悉这种实践的好时节。Manning出版社出了几本关于JUnit的书,那是编写Java单元测试的事实标准库,还有《JUnit in Action》(第2版,作者Petar Tahchiev等,2010年7月出版),是测试各种Java代码的优秀入门教程,涵盖从简单Java对象到企业级JavaBeans。
假如你在家自己编写单元测试,但却不熟悉Java或JUnit,或许你该先看看本书的附录A,这样在阅读例子时就不会有麻烦了。
自动化测试成为主流,并不意味着我们的测试覆盖率已达到理想状态,或者生产力无法再改善了。事实上,我在过去五年中的大量工作正是帮助人们编写测试,在编码之前写测试,特别是编写更好的测试。
为什么编写更好的测试这么重要?如果我们不注意测试的质量,那又怎样?我们现在谈谈测试带给我们什么价值,以及测试质量为什么重要。
1.2测试的价值
来认识一下Marcus。Marcus是著名的编程奇才,两年前刚毕业,然后加入了本地一家投行的IT部门,为银行开发用于在线自助服务的Web应用程序。作为团队中最年轻的成员,起初他保持低调,集中精力学习银行的领域知识,熟悉“这里做事的方式”。
几个月后,Marcus注意到团队的工作很多都是返工:修复程序员的错误。。他开始关注团队修复错误的类型,发现单元测试可以轻易地捕获到大多数的错误。当他感觉到哪里存在特别容易出错的代码时,Marcus就对其编写单元测试。
测试帮助我们捕获错误。
一段时间以后,团队其他人也开始到处编写单元测试。Marcus已被测试感染(test-infected)了,他碰过的代码几乎都具有相当高的自动化测试覆盖率。除了在第一次时犯错,他们不会再花费时间修复过去的错误,待修复缺陷的总数在下降。测试开始清晰可见地影响着团队工作的质量。
自从Marcus编写第一个测试,已经过去近年了。在前往公司圣诞派对的路上,他意识到时光匆匆,于是开始回想这段时间内发生的变化。团队的测试覆盖率在近几个月快速提高,达到了98%的分支覆盖率。
Marcus曾认为他们应该推动那个数字直到100%。但过去几周,他打定了主