弃用测试驱动开发(TDD)

发表于:2016-04-06来源:infoq作者:Abel Avram点击数: 标签:测试驱动开发
Ian Sommerville是一名退休的大学软件工程教授,他已经写了好几本书,包括《软件工程(第10版)》。该书第8章专门介绍了软件测试,其中8.2小节特别介绍了TDD。他在个别章节中多次重申了

  本文汇总了一个大学教授放弃使用测试驱动开发(TDD)的经过以及鲍勃大叔对其论点的反驳。

  Ian Sommerville是一名退休的大学软件工程教授,他已经写了好几本书,包括《软件工程(第10版)》。该书第8章专门介绍了软件测试,其中8.2小节特别介绍了TDD。他在个别章节中多次重申了其中的部分观点。在最近的一篇博文中,Sommerville写道,“TDD是软件工程的一次重要进步。显然,TDD适合某些类型的系统”,他列出了下面这些“TDD友好”的系统:

  分层架构;

  成功标准一致的系统,测试围绕这些标准构建;

  操作环境可控,不必同超出控制的系统交互。

  Sommerville补充说,对于这样的系统,TDD很有效,但他发现TDD很难用于其他类型的系统:

  我在一类符合这些标准的系统上开始使用TDD,我喜欢它。对我而言,它很有效。后来,我转到了一个涉及可视化复杂链接结构的系统。现在,关于可视化,(a)往往很难有一个明显分隔的层——UI就是程序,(b)很难预定义成功标准——基本上必须通过试验看看什么有效什么无效来编程。TDD就不合用了。

  Sommerville还写了一篇博文“放弃测试优先的开发”,分享了他最近在一个私人项目中使用TDD的经历。他发现,TDD在开始时很有帮助,但后来,当开始GUI研发的时候,他发现编写测试越来越难,而且他认为编写测试花费的时间不值得。因此,他有时候会在编写测试之前编写实现代码,并在稍后增加一些测试。最终,他放弃了TDD,他的解释是:

  我放弃TDD,不是因为编写GUI自动化测试时(众所周知的)的困难。我放弃是因为我认为TDD鼓励保守编程,它会促使你制定可以测试的设计决策,而不是对程序用户而言正确的决策,它让你关注细节而不是结构,而且,对于一大类程序问题——那些由异常数据导致的问题——它不是很有效。

  Sommerville继续说明了一些细节:

  TDD鼓励保守:人们不愿意对应用程序做重大修改,因为他们知道许多测试会被破坏,他们必须重写。

  “有时候,最好的设计是最难测试的那一种”。

  TDD将注意力放在了细节上而不是整体。“使用TDD,你会陷入到程序不同部分的细节中去,很少回过头来看看全局。”

  很难为异常数据编写测试。

  因此,他决定首先编写代码,然后再测试。但是,有人注意到了他的博文。Robert C. Martin(又名鲍勃大叔)对Sommerville放弃使用TDD的观点提出了反对意见。鲍勃大叔认为,Sommerville遇到的是初学者的麻烦,他放弃得太快了。修改系统的一个组件又会破坏另一个组件,这是因为系统的两个部分是紧紧耦合在一起的。当一个人因为害怕破坏所有的测试而不敢重构代码,那就意味着测试同生产代码绑定的太紧。我们应该将系统组织成独立的层,每个层应该通过接口提供访问,测试也会使用这些接口。

  鲍勃大叔反驳了“最好的设计是最难测试的那一种”的观点,认为那是胡说。一个无法测试的设计很可能在需要它的时候不能发挥作用。在困难的情况下,比如测试GUI或设备驱动,他提到使用The Humble Dialog Box模式这个选项。

  鲍勃大叔不同意TDD太过关注细节的观点。他认为,一名开发人员应该总是设计:

  不管编写什么;单元测试,或者验收测试,或者生产代码,或者“模拟(mock)”,或者“桩(stub)”,都必须设计……

  我们是程序员!我们设计!我们创建高内聚低耦合的结构。我们管理依赖。我们隔离模块。我们,设计。

  鲍勃大叔继续写到,程序员有时会忘记设计。尤其是某个领域的新手往往关注特定底层的细节,因为他们在学习过程中。他强调了心中有全局的重要性,让我们想起了Ron Jeffries(XP合著者及敏捷宣言签署者)的建议:“全局思维,局部行动。”

  最后,鲍勃大叔也同意,很难考虑异常情况,但那不是TDD的错:

  阿波罗1号导致了火灾。阿波罗13号在去往月球的途中爆炸了。挑战者号刚发射就爆炸了。哥伦比亚号返回过程中解体。为什么?因为尽管成千上万的大脑试图考虑到一切情况,但还是有一些未能预见到的情况出现了……

  面对现实吧。总会有风险。不要责怪TDD,也不要放弃。

  Israel Fermin Montilla是一名软件工程师,他的立场比较温和,他对Sommerville的博文作了这样的评论:

原文转自:http://www.infoq.com/cn/news/2016/03/tdd