弃用测试驱动开发(TDD)

  • Abel Avram
  • 谢丽

2016 年 3 月 25 日

话题:语言 & 开发

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

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

  1. 分层架构;
  2. 成功标准一致的系统,测试围绕这些标准构建;
  3. 操作环境可控,不必同超出控制的系统交互。

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 的博文作了这样的评论

我相信,有关编写测试的事情不是说先写或是后写,而只是要写,有测试维护原则,并严格遵守你希望一个特定项目需要达到的代码覆盖量。先写有明显的好处,但那不是一项对每个人或对每个项目而言都有效的技术。根据我的经验,有时候会有一些时间限制,迫使你快速实现,然后只测试关键环节。我一直在创业公司及互联网公司工作,那是一个节奏非常快 / 注重市场的环境,为了发布并获得用于评估的数据,有时候你会欠下大量的技术债务(尤其是在创业公司的早期阶段)。

查看英文原文:Giving Up on TDD

语言 & 开发