InfoQ

新闻

关于TDD的观点:质量是反复思考的结果,仅靠解决Bug无法获得

作者 Abel Avram译者 乔梁 发布于 2008年7月7日 上午7时56分

社区
Agile
主题
敏捷技术,
单元测试
标签
评论,
极限编程,
测试驱动开发,
测试

通过单元测试可以改善代码质量”这一观点已经得到广泛认可。培训师、顾问兼咨询师Michael Feathers在最近的帖子中对其提出了质疑。他谈及单元测试、集成测试、TDD和净室软件开发(Clean Room Software Development),认为代码质量是反复思考的结果,仅靠解决bug无法获得。M3P的独立咨询师Steve Freeman进一步阐述了Michael的观点,从“认知方面对TDD进行了分析”,并解释了TDD的好处从何而来。

Michael认为,利用测试找Bug来改善质量的想法是有不足之处的

对于单元测试,最常见的理论就是“通过解决测试找到的bug,软件的质量得以提升”。乍听起来,好象没错儿。测试有通过或失败两种结果,一旦失败,我们就知道肯定是有什么地方出了问题,就要修复它。假如你赞同这个说法,你就会预期在做集成测试时发现更少的集成错误,在做单元测试时也是一样。这个观点貌似挺好,不过它是错误的。能够证明这一点的最佳方法就是:将单元测试与另一种提高质量的方法相比较,而且这种方法有着很好的度量效果。

为了证明他的观点,Michael提到净室软件开发(Clean Room Software Development),这是一种在上个世纪八十年代曾被使用的开发方法。根据Michael所述,净室方法不包括任何单元测试过程:

净室方法背后的观念,就是要通过更严格的开发纪律来提高质量;在净室中,你要为每一小短代码写逻辑断言;在代码复查时,你还要证明代码的功能和你写的断言完全符合,功能不多也不少。这种方法非常严格,甚至比我所说还要极端,因为净室方法的另一个宗旨是:不能有单元测试。一个都没有。毫无必要。代码开发完成之后,只要被复查过就被认为是完全正确的。唯一的测试就是在功能层面的随机测试。

使用净室方法的结果很有趣:不经任何单元测试,代码质量也提高了。净室方法和TDD方法的相似之处在于:迫使开发人员不断复查、重构并改进他的代码。Michael的结论就是:

我认为,我们不能机械地看待测试。单元测试并不能在“单元”这个层次上通过抓到错误来改进质量。而且,集成测试也不能在“集成”这个层次上通过抓到错误来提高质量。实际上背后的道理难以言说。质量是反复思考的结果——严谨的反复思考。这就是关键。强化纪律的技术一定会提高质量。

从Michael的帖子出发,M3P的独立咨询师Steve Freeman进一步阐述了这个观点,并谈到“对TDD在认知上的分析”。开发人员的某些决定会影响他们的代码:

事实证明,人们并没有真正花时间从各种可行的方案中进行权衡,而是使用了“首先契合(first-fit)”的方法,即将已知的解决方案按序排列,然后选择第一个看上去最好的方案。所有这些都是在潜意识下发生的。在这之后,我们迟钝的理性思维才会想办法证明这个已成事实的决定——我们甚至都不知道这些是如何发生的。

关键在于不要直接采纳第一个在我们脑海里出现的解决方案,而是要评估不同的可选方案,这就是Steve认为TDD有益的原因:

测试驱动开发打破“首先契合”这种模式匹配,从而发挥了(或应该发挥)作用。通过TDD,我们不再强制用脑海中出现的第一方案来解决问题。我们也不得不远离自己的“安全地带(comfort zone)”来考虑真正需要实现的需求。更重要的是,从“写一个测试开始”迫使我们首先去想真正需要的是什么(要测试什么),然后再用我们专家般敏锐的大脑来得出解决方案。

Steve举了一个例子来证明他的观点:

最有力的证据就是Arlo Belshee所在的小组,他们实现了无序结对编程(Promiscuous Pairing)。他们从经验中发现:相对于成员自己决定结对时间,强制他们每隔几个小时就切换结对,这样的生产率最高。他们认为,这样可以保持每个人处于“初学者”的心态,也就可以像“初学者”那样思考。
英文原文链接:TDD Opinion: Quality Is a Function of Thought and Reflection, Not Bug Prevention

相关赞助商

InfoQ中文站敏捷社区,关注敏捷软件开发和项目管理,通过新闻、深度文章、视频访谈和演讲以及迷你书等为中国技术社区提供一流资讯。

没有回复

回复

独家内容

书评:敏捷模式──指向成功的路标

Ryan Cooper对Amr Elssamadisy的新书发表了评价,并认为书中提供了一种为实施敏捷量身定做的框架。本书并没有给出一种人人可用的敏捷方法,而是为读者提供一些模式和工具,用以找出哪些敏捷实践可以最有效地达到该组织机构的特定目标。

构建的可伸缩性和达到的性能:一个虚拟座谈会

这个由业界主要专家们参加的座谈会探究了在使应用程序具备尽可能好的伸缩性及性能的过程中所面临的挑战和思考过程。

OpenSocial的分析与实现

本视频主要对OpenSocial进行了分析,并对实现的方式进行了介绍。其中包括:OpenSocial的开发经验、Container Provider的技术准备、平台的构成要素、具体的规范、以及对未来的展望。

缓存系统MemCached的Java客户端优化历程

Memcached在大型网站被应用得越来越广泛,但是Java客户端并不多,本文作者基于现有的开源客户端进行了封装优化,并翔实记录了这一过程。

超越SOA:动态业务应用的新企业应用框架(2)

在他们文章的第二部分,作者探讨了动态业务应用的架构并介绍了资源容器的概念。他们示范了如何在JEE之上构建这个架构,以及它如何影响实现生产力。

使用ClickOnce细分发布版本

ClickOnce让WinForms应用程序的部署轻而易举。David Cooksey演示了如何在ASP.NET中编写一个HttpHandler来实现对ClickOnce部署的版本细分。

敏捷教练,从A到Z

敏捷带来了新的领导者角色,“敏捷教练”。它是不是跟“部门经理”或“技术领导”一样,只是换汤不换药呢?教练Pat Kua在这篇启蒙文章中对敏捷教练一职做了概述。

利用Ruby简化你的Java测试(进阶篇)

本文是Productive Java with Ruby系列文章的第二篇,通过上一篇的介绍,我想大家对如何利用Ruby进行单元测试有了一个基本的了解,从这里开始,我将和大家一起讨论一些利用Ruby进行单元测试时的高级话题。