测试驱动开发介绍
本文摘自《测试驱动开发——实战与模式解析》一书的前言。
“可运行的简洁的代码”是 Ron Jeffries 关于测试驱动开发(Test-Driven Development,TDD)目标的精辟概括。有一大揽子理由能够说明,可运行的简洁的代码是值得实现的目标:
- 它是一种可预测的开发方式。你会知道自己何时可以完成,而不必担心因缺陷而拖得太久。
- 它会给你全面认识代码的机会。如果你草率地采用了自己最初的想法,那就再也没有时间来考虑另外更好的想法了。
- 它让使用我们软件的用户生活变得更加美好。
- 它使成员之间相互信赖。
- 它本身的编写过程让人感觉很棒。
但我们如何才能得到简洁的可运行的代码呢?很多因素使我们与简洁的代码渐行渐远,甚至导致代码无法运行。其实,不用为我们的担心浪费太多笔墨,这样做就可以:使用自动化测试驱动开发,一种叫做测试驱动开发(简称 TDD)的开发方法。在测试驱动开发中,我们:
- 仅当自动化测试失败的时候才编写新的代码。
- 去掉重复的部分。
这是两项比较简单的原则,但这会产生出一个或者一组技术方面复杂的行为准则,例如:
- 我们必须参考每次修改后的代码运行状况的反馈,逐渐完成设计。
- 我们必须自己编写测试,因为我们不能指望其他人编写测试。
- 我们的开发环境必须对细微的修改迅速做出响应。
- 我们的设计必须遵从高内聚、低耦合的原则,这样便于实施测试。
那两项简单的原则预示了编程任务的先后顺序:
- 红色指示条——编写一个无法工作的简单测试,当然,这个测试起初甚至都无法通过编译。
- 绿色指示条——迅速使测试工作起来,这个过程可谓想方设法,甚至不择手段。
- 重构——去掉单纯由于使测试工作起来而产生的重复部分。
红色指示条-->绿色指示条-->重构 —— 此乃 TDD 的经典三部曲。
先假设这样的编程方式是成立的,进一步讲,这种方式可使代码缺陷的密度降低,还可以使所有相关人员对工作主旨若网在纲。如果这样的话,只在测试失败时才需要编写的代码还有其社会意涵:
- 如果可以将缺陷的密度降到足够低的话,那么,质量保证人员的工作状态就能够变被动为主动。
- 如果可以尽可能地减少令人不悦的意外发生,那么,项目管理人员就可以非常精确地估算出日常开发工作所需的人手。
- 如果可以将技术讨论的主题构思地足够清晰,那么,软件工程师就可以亲密无间地合作,而非拉锯式地工作。
- 同样,如果可以将缺陷的密度降到足够低,那么, 我们每天都可以发布带有新功能的软件,这样会与客户建立新的业务往来。
诚然,这个理念并不复杂,但是其背后的动机又是什么呢?为什么一位软件工程师要插手编写自动化测试以外的工作呢?为什么一位软件工程师能够给出高层建瓴的设计却以细微的步伐前进呢?勇气使然。
勇气 ( Courage )
测试驱动开发是一种在编程过程中管理担忧的方式。
测试驱动开发是一种在编程过程中管理担忧的方式。这不是杞人忧天之虑,而是合理的担忧,但是否合理的问题是很难从一开始就看出来的。如果疼痛的自然反应是喊“停”,那么担忧的自然反应则是喊“当心”。当心历来是好事,但担忧却有不少其他的副作用:
- 担忧使你举棋不定。
- 担忧使你疏于交流。
- 担忧使你回避反馈。
- 担忧使你郁郁寡欢。
这些作用对于编程都是无益的,尤其是在编写有难度的程序时。因此,你该如何面对困难的局面呢?并且:
- 尽快开始具体地了解一些东西而不是试探。
- 更加清晰地交流而不是闭口不言。
- 找出具体的有用的反馈而不是回避。
- 克制负面情绪。
把编程想象成使用曲柄从一口井中摇上一桶水的过程。当水桶不太大时,自由旋转的曲柄还不错。当水桶比较大并且装满水,再把水桶提上来的时候,你就会感到累了。你需要一个在转动曲柄的间隙能够使你休息的棘齿装置。越重的桶,就需要棘齿装置的齿越密。
测试驱动开发当中的测试就像棘齿装置的齿。一旦测试运行起来,你就知道它会这样子运行下去了。比起测试坏掉的情况,你已经朝着一切运行如仪的目标又迈进了一步。现在,还可以使下一个,下下个和再下一个测试运行。以此类推,越是棘手的变成问题,每个测试的覆盖面要越小。
测试感染 ( Test Infected )
大多数学习 TDD 的人发现他们的编程行为被永远地改变了。测试感染是 Erich Gamma 发明的用来描述这一转变的说法。你可能会发现自己比以前会写更多的测试,会发现使用更小的步伐推进要比曾经自己想象的要合理。另一方面,一些软件工程师学习 TDD 后保留了他们原有的编程行为,在一些特殊的情况下,当常规的编程方法不奏效的时候,他们才拿出 TDD 救急。
测试不适用场景
存在不能仅仅(或者根本不能)由测试来驱动的编程任务,例如,软件安全性和并发问题,使用 TDD 去一板一眼地证明这两方面与需求的吻合度就会显得捉襟见肘。尽管事实上软件的安全性本质上依赖于无缺陷的代码,但也依赖于使软件变得安全所使用方法的人为判断。微妙的并发问题是不能通过运行代码就能可靠再现的。
畅想
发挥你的想象力想象一下,一个所有代码都简洁明了,不存在复杂解决方法的编程世界,仅有复杂的问题需要认真思考。那么,TDD 完全可以帮助你得偿所愿。
让我们开始 TDD~~~