测试驱动开发(TDD)是近年来“敏捷革命”中最热的话题之一,但是,市面上鲜见与此相关的有深度的作品。这本书的出版填补了这个空白,满足了众多一线程序员的需要。作者Davis Astels将这本书看作是Kent Beck的经典作品《Test Driven Development By Example》(英文影印版及中文版由中国电力出版社出版)的补充,重点阐述利用TDD开发所必要的技术和工具上,因此对实际开发更具实用性。
本书共分五部分。首先介绍了与TDD有关的基本主题,例如重构、意图导向编程(programming by intention),当然还有TDD背后的原理剖析。接着深入分析了一些工具和技术,例如JUNIT、模拟对象(mock objects)。第三部分主要讲解如何将TDD应用到一个真实Java项目,这是本书的精华所在,作者亲自带你进入TDD世界,告诉你如何将看似复杂的“测试为先”在项目开发中尽情演绎。第四部分逐一概述了xUnit家族成员,如RUBYUNIT、SUNIT等。附录包含极限编程和敏捷开发的入门材料,以及一些在线资源。
本书还包含了大量练习题并附有详尽的参考答案,以方便读者的学习,加深读者对本书内容的理解。
I 背景知识介绍
1 测试驱动开发
什么是测试驱动开发?
让计算机来告诉你
一个简短的例子
小节
2 重构
什么是重构?
什么时候进行重构
如何重构
一些重要的重构方法
通过重构来引入模式
小节
3 意图导向的编程
名字
简单
要做有根据的假设
如何进行意图导向的编程
“无需注释”
小节
II 工具与技术
4 JUnit
体系结构概览
断言
编写一个测试用例(TestCase)
运行测试
使用setUp()和tearDown()
使用TestSuite()
相互关系
测试的归属问题
一些建议
小节
5 JUnit的扩展(extensions)
标准扩展
使用MockObjects补充的断言
使用JUnitPerf来来测试性能与可伸缩性
Daedalos JUnit扩展
使用xmlUnit来编写基于XML的测试
Gargoyle 软件公司的JUnit扩展
6 与JUnit有关的工具
Jester
NoUnit
Clover
Eclipse
IDEA
7 模拟对象(Mock Objects)
模拟对象
例子解说
模拟对象的用途
如果能这样该有多好?
一个普通的例子
MockObjects框架
MockMaker
EasyMock
小节
8 以测试优先的方式开发一个GUI应用
例子
AWT机器人
蛮力测试(Brute Force)
JFCUnit
Jemmy
超瘦(Ultru-Thin)GUI
小节
III 一个彻头彻尾的采用TDD开发的Java软件项目
9 项目描述
概述
用户描述及相关任务
10电影列表
为电影制作一个容器
为电影列表创建GUI
通过GUI增加电影
回顾
11可以为电影更名
支持对电影名的编辑
对电影更名的GUI
回顾
12电影是唯一的
电影是唯一的
发现不唯一时的出错信息
回顾
13评分(ratings)
给电影打分
在GUI中显示评分
对评分进行编辑
回顾
14类别
增加一种类别
在GUI中显示类别
提供可供选择的类别
回顾
15根据类别进行筛选
获得基于类别的子列表
支持一种称做ALL(所有)的类别
在GUI上添加类别选择器
处理电影类别的变更
界面修整
回顾
16持续性存储(persistence)
将数据输出到平直文件中
GUI中的Save-As菜单项
GUI中的Save菜单项
从平直文件中读取数据
加载到GUI中
回顾
17排序
电影比较
对电影列表进行排序
从MovieListEditor中获取排序后的列表
在GUI中增加排序操作
回顾
18多重评分
多重评分
评分来源
修正后的持续性存储
在GUI中显示电影的多重评分
在GUI中添加增加评分的功能
删除单一评分域
回顾
19评论
为评分附加评论
保存评论
加载评论
显示评论
增加评论
回顾
20项目回顾
设计
测试代码 vs. 应用代码
测试质量
模拟对象的使用
总体评述
调试
测试清单
小节
IV xUnit一族
21RUBYUNIT
22SUNIT
23CPPUNIT
24NUNIT
25PYUNIT
26VBUNIT
V附录
A 极限编程
敏捷革命
极限编程
四种变化量(The Four Variables)
价值观(Values)
实践方法(Practices)
小节
B 敏捷建模
与建模有关的荒诞言论
敏捷建模(AM)导论
什么是敏捷模型?
C 联机资源
论坛
与敏捷建模有关的信息
与极限编程有关的信息
与JUnit有关的软件
与JUnit有关的信息
各种工具
XUnit家族的其他成员
相关公司
杂类
D 练习答案
参考文献
索引
本书并不是一本有关测试的书籍。
这是一本可以使代码变得简单、清晰、健壮的编程方法。它可以使代码易于设计、编写、阅读、理解、扩展和维护。
这是一本有关思考、设计、沟通以及编程的书。作为一种非常好的副作用,我们最终将会得到一套详尽的(1)测试集。
本书探讨的内容是测试驱动开发(Test-Driven Development)或测试优先编程(Test-first Programming),不管你怎么称呼它,它都是在指一种先编写测试,然后再编写让测试获得通过的代码的方法。具体而言就是以尽可能小的步伐推进:编写足以失败的测试代码,编写足以让测试通过的产品代码,通过重构来整理为使测试通过而引入的混乱代码。
本书着重使用Java编程语言,通篇都使用用Java编写的例子。我们假定读者至少对Java(如果想要亲自动手尝试一下书中的例子的话,还要有一套能够工作的Java系统)有中等程度的了解。大家可以从我的Web站点[URL 54]获得范例代码以及其他一些辅助资料。
尽管我们将重点放在Java上,但是本书的第四部分还是查看了其他一些重要的针对几种流行编程语言的xUnit家族成员。我们选取第10章中的第一项任务,分别用各种语言重新予以实现,这样就各种不同的测试框架而言提供了很好的比较。
(1)究竟有多么详尽要看你对TDD掌握的有多好。
极限编程
测试驱动开发(Test-Driven Development)是由Kent Beck形式化(formalized)的一种称做极限编程(eXtreme Programming - XP)的敏捷软件开发过程(agile process)的核心部分。XP很可能是敏捷软件开发过程中最“敏捷”的部分了,它开销极底,繁缛极少,然而却是一种高度自律,非常高效的软件开发方法,对变化有着难以置信的适应能力。
也就是说,为了运用测试驱动开发方法(TDD)进行开发并从中获益,您不必采用极限编程过程(XP)。单就测试驱动开发本身而言也是值得的,你的产品代码质量一定会改善。当然如果采用极限编程过程的话,那么真正熟练地使用测试驱动开发方法对于选用这种开发过程来说才是值得的。
测试驱动开发是极限编程中一项主要的设计工具(2)。如前所述,产品开发终了所拥有的整套测试是一种非常令人愉快的副产品。因为有了那些测试,当我们在代码修改前后运行测试并且通过的话,就可以确信自己在此期间没有意外地引入使产品无法正常运行的错误。反之,如果某项测试在代码修改以后无法运行通过,那么我们就可以知道究竟是哪个地方出了问题,而能够方便的找出问题并且修正它。唯一可能造成错误的位置就是在上次测试运行通过以后修改的地方。
(2)另一项是重构。
所有这一切都意味着由于测试的存在,我们可以安全地使用极限编程的另一种方法:重构(Refactoring)。正如我们将要在第12章看到的,重构就是在不改变代码外部行为的情况下对代码的结构进行调整。我们有测试可以保证行为没有被改动。这样你就有了修改(有时这种改动是翻天覆地的)工作代码所必需的自信,而我们最终的代码也会更清晰,可扩展性更好,可维护性更强而且更易于理解。
附录A更多的谈到了有关极限编程的内容。要想更多的了解有关这方面的知识,您可以浏览一下参考文献或访问附录C中所列出的极限编程(XP)联机资源。
谁应该阅读本书?
你应当读这本书吗?我写这篇前言的目的就是要问答这个问题。以前在雅虎极限编程讨论组(XP Yahoo Group)中有一项关于图书的前言应当服务于什么目的的调查。大家总体的意见是通过阅读前言应当能够比较清楚的知道自己是否应当购买或阅读某一本书。希望我在此很好的履行了这一种义务。
如果你想采用极限编程,那么就请阅读本书。如前所述,要想能够较好地掌握极限编程,那么花些时间和精力来较好的掌握测试驱动开发是值得的。测试驱动开发在极限编程中处于核心位置,因此较好的掌握了测试驱动开发就可以使整个极限编程过程的效率大为提高。
如果你想编写出更加清晰、健壮、扩展性强而又尽可能精练(而不是臃肿)的代码,那么请阅读本书。
如果你对在开始编写代码之前花费数周或数月时间绘制各种设计图例心存异议的话,那么请阅读本书。
最后,如果你想知道如何才能使编程工作再度充满乐趣的话,那么就请阅读本书。
在阅读本书之前,就所应当了解的知识而言,如果你对Java至少有中等程度以上的了解,那么会更好一些。如果你以前对其他几种面向对象编程语言(如Smalltalk、C++、Python或Ruby)有较好的掌握的话,那么就可以从本书中汲取到更多有用的知识。
在本书付印的时候,市面上还有另外一本有关测试驱动开发的书(我知道大家对这本书肯定趋之若骛)。在本书编写大半的时候,我了解到还有这样一本书也正在编写,所以作为对那本书的补充则一直是本书所要达到的部分目标。通过阅读那本书,你能够领悟测试驱动开发本质和抽象层面的东西,那本书也包含了足够的实用范例。如果你倾向于那本书,那么我鼓励你先阅读它。现在你手里拿的这本书,正如书名所讲的,是一本有关测试驱动开发的实用指南。本书把重点放在一种语言(虽然不是最好的语言,但无可争辩的是一种非常流行的同时也是对测试驱动开发支持良好的语言)上,不仅阐述了测试驱动开发的概念和原则,同时也对各种工具和技术进行了清晰的阐述。
本书的结构
本书分为四个部分:
I 背景知识介绍 在第一部分我们考察了一些与书中的主要内容(即利用Java来进行测试驱动开发)有关的话题。我们开始先对测试驱动开发作一介绍。然后分章节讲述有关重构(refactoring)和意图导向编程(programming by intention)的知识。这两种技术在极限编程中也是非常重要的,是测试驱动开发所要求的,同时又是测试驱动开发才使之成为可能的。
II 工具与技术 在第二部分我们深入探讨了各种对使用Java来进行测试驱动开发有用的工具以及如何来使用这些工具。我们先是提供了一篇介绍JUnit的教程,JUnit是Java测试驱动开发框架事实上的标准。接着我们探讨了一些JUnit的标准或非标准扩展。随后探讨了一些支持使用JUnit的工具以及其他一些完全独立于JUnit但是能够与之很好配合的工具。这一部分的最后一章考察了某些特定的技术问题和其相关工具。
III一个彻头彻尾的采用TDD开发的Java软件项目 这是一本重在亲身实践的实用指南。所以在第三部分,我们围绕如何开发一个真实的系统来展开。这可不是一个随随便便的例子。我们将采用测试驱动开发的方法来开发这个项目。在此过程中,我们将会用到书中前几部分所讲的内容。
IV xUnit一族JUnit只是大的正在成长中的程序员测试框架(programmer test framework)中的一个成员。我们将在第四部分查看一下这个家族中的其他一些成员。我们不会把所有的成员讲解一遍,但是会讲到几种较为流行的编程语言的测试框架。我们针对每种测试框架,根据同一组描述(即需求),使用不同的语言重新编写了程序,这样它们之间也就有了一个很好的比较。具体而言,这几个描述就是Java项目中开始的那几个描述。同时这也可以使我们拿各种测试框架与JUnit作一比较。
本书有四个附录:
A 极限编程 这个附录简明扼要的介绍了有关极限编程的知识。
B 敏捷建模 该附录概括描述了有关敏捷建模的内容。
C 联机资源 在本书讲解过程中我引用了一些Web站点,大家可以在这些站点上找到一些相关的信息或下载资源。该附录提供了附带注解的分类资源列表。
D 练习答案 书中的许多章节都包含有让读者完成的练习。该附录包含了书中的全部练习和参考答案。
为了便于大家阅读,我在书中使用了不少可视化的约定表达方式,用以区分不同种类的信息。
源代码 本书包含了大量的源代码,代码行缩进并以sans-serif字体来表示, 如下所示: public int getAverageRating() { return totalRating / numberOfRatings;
当在正文中引用一行代码的部分内容时,仍然使用同样的字体来表示。这些内容通常包括类名(Movie),方法名(equals())和常量(true, “a string”, 42)。
总体而言,在引用某个方法的时候,我们没有把参数也包括在内,而是使用空括号,这样就可以清楚的表示这是一个方法而不是某种其他类型的标识符,例如aMethod()。
我们一般会省略成块代码中的package和import语句。
文件系统及主控I/O 我们使用等宽serif字体来表示指代文件系统的内容。这些内容包括文件名(filter.properties)、命令及其输出等: P-xviii 建议与旁注 我使用了多种不同的表现形式来强调那些值得注意或是有趣但因为某种原因不适合在正文中叙述的重要信息。
这本书中穿插了一些小经验,也许您会觉得特别有用,所以我们把这些内容单独分出来,本段内容就是出于这个目的。
这是一段非常简短的旁注的例子;大多数旁注都只有半页或一页的篇幅。
我使用旁注来把那些与正文没有直接关系的小段文字分离出来。这些旁注的位置是由LaTeX自由设定的,通常位于每一页的顶端。这里就有一个旁注的例子。