翻译:《为什么大多数单元测试是浪费》索引

版权声明:所有博客文章除特殊声明外均为原创,允许转载,但要求注明出处。

TDD (测试驱动开发)是敏捷开发、特别是极限编程(XP)的核心实践之一,也是我长期以来一直坚持采用的方法。因此,当我最近偶然从一个链接发现这篇文章时,它带给我的震动是可想而知的。虽然在之前我也模糊地感觉到单元测试可能存在的一些问题,但一直相信是自己水平不够、认识有限的原因,没有更深入地思考过。也曾听说过 DHH(Ruby on Rails 框架的作者)对 TDD 的反对意见,但也只是想那可能是 RoR 框架本身的局限,不一定是广泛适用的结论。

《为什么大多数单元测试是浪费》(Why Most Unit Testing is Waste)这篇文章是完全不同的:它从信息论和开发过程本质的层次上揭示了单元测试所固有的根本性缺陷,同时也引用了大量学术论文与研究成果,证明单元测试在实践上的成本效益是非常有限的。作者的结论,并不是要完全取消单元测试,而是应该严格限制单元测试的使用。重要的论点包括:

  • 单元测试应该仅用于关键性的独立算法;
  • 不要用测试驱动设计,而是需求驱动设计;
  • 对于业务组件的正确性验证应该使用集成测试或系统测试;
  • 综合使用多种质量保证手段,包括调试和代码审查;
  • 扔掉一年以内从未失败过的测试;
  • 将测试转换为断言;

必须承认,我自己一直是敏捷的拥护者,所以我在看到题目的时候已经抱着怀疑的态度,只是出于“兼听则明”的克制才点开该文章的。但是阅读全文后,我被说服了。这并不是某个半吊子的开发者在抱怨自己的主观感受,作者是有着多年经验的开发者和顾问,其内容深度和完整性远远超过了我的预料,并且(我个人认为)论证过程是非常有说服力的。尤其是从成本和收益角度,客观地分析某个实践的具体效果,而不是一再重复某些无法证明的个人信条,这是我特别欣赏的。同时,该文章也让我对自己多年来一直抱有的一些模糊的疑问进行更深一层的思考。

当然,我也不是完全同意作者的论点。比如“扔掉一年内从未失败过的测试”这一条,虽然从理论上讲是有意义的,但是现实中我相信大多数老板——或者项目经理应该不会采纳,因此可行性是个大问题。尽管如此,从总体上讲,不论你赞同或反对作者的观点,认真看一看该文章的内容,都会是很有益处的。

该文章并不是什么新内容了——最早发布的时间应该在 2014 年。文章内容发表以后在网络上引起了广泛的注意和争论,因此作者后来又补充了一篇,对前文内容进行补充说明,并回复了网络上的部分意见。该文章可能在国内没有引起多少注意,因为我进行了一些搜索,发现在中文网络上几乎找不到该文章和相关的讨论(我自己以前也没有发现该文章)。

熟悉我的人可能知道,对于技术性文章,我一向是鼓励开发者主动阅读英文原文的。但对该文章,我考虑以后觉得,一是文章内容不同于普通的文档或教程,技术性和理论性很强,如果没有翻译的话,可能很多开发者会很难以理解;另外,考虑到国内普遍不了解该文章的现实,有中文内容也更有利于知识的普及和传播。因此,我不揣冒昧,向原作者申请翻译文章,并得到了授权。

但真做起来才发现这是个苦差事。原文章的技术性很强,包括不少学术内容和数学理论,我虽然大致猜得到文中的意思,但是清晰的表达出来又是另一回事。此外,文中有很多意义相近、但有微妙不同的术语,比如 error/fault/failure/anomaly/bug,再比如 verification/validation,当它们放在一起时,我苦思冥想了很久也不知道该如何用中文确切表达出它们的细微差异。因此,我对部分可能影响阅读的地方加了注释,希望能对读者朋友有所帮助。如果发现翻译内容不知所云,那么责任在我。原始文章链接将在末尾给出,以供参考。无论如何,我还是建议有兴趣的朋友读过翻译以后,再去认真读一读原文(虽然这是个很花精力的过程,建议最好同时打开在线字典)。

前面也说过,该文章发表后曾在网上引起广泛关注与争议。你可以通过搜索引擎找到很多第三方对该文的评论与引用,不过已经有开发者 Keith Pitty 为此制作了一个长达 60 页的 slideshow,其中包括许多行业大佬的意见汇总和相关资源,是一个很好的参考。读者也可以从这里开始浏览其他的信息,链接我也会在末尾一并给出(可能要翻Q)。

如果作者的深度文章(以及我的翻译)能够对爱思考的开发者带来一些启发,那么我的目的也就达到了。

翻译说明

原文中有些反复使用的术语,比如 “oracle”,其含义并未明确说明,可能会在一定程度上影响阅读。综合上下文判断,“oracle” 应该是指独立制定的(相对于开发者自己编写),对于软件或算法的行为进行明确规定,其严格的定义基本上可以直接推导出到具体的测试用例。同时,它应该有很高的权威性。其具体形式可以为严谨的文档、需求规格、BDD 规约,甚至可以是有话语权的业务分析师。由于在中文中很难找到准确的对应词,所以我简单翻译为“神谕”(当然不是那家臭名卓著的公司啦)。希望大家了解这个背景,在阅读时结合上下文具体判断。

另外,某些地方出现的“绿条”是指单元测试工具显示的结果界面,通常用绿色表示全部测试通过,而红色代表有异常或失败的测试。这对于有单元测试背景的同学来说是显而易见的,对于没有相关背景的同学,我在这里做个说明,免得大家看到 “Green Bar” 不知道它在说什么。

翻译系列:

参考资源: