1:什么是TDD?¶
测试驱动开发,或称TDD,是一种迭代的方式,通过测试支持的许多小变化来创建软件。

它有四个步骤:
- 编写一个失败的测试
- 使测试通过
- 重构
- 重复进行
这就是所谓的TDD循环。它确保你彻底和准确地测试你的代码,因为你的开发是...由测试驱动的
通过写一个测试,接着写生产代码使其通过,你确保你的生产代码是可测试的,并且在开发过程中满足所有要求。作为额外的奖励,你的测试作为生产代码的文档,描述了它是如何工作的。
表面上看,TDD过程似乎很简单。好吧,我很抱歉地告诉你......等等,它实际上是非常简单的!你知道吗?
当然,对于如何实现这个循环,有时会有一些特殊的情况,但这正是本书的作用所在! 一旦你掌握了这个过程,它将成为你的第二天性。在下一章中,你会学到更多这方面的知识。
你为什么要使用TDD?¶
TDD是确保你的软件工作并在未来继续工作的唯一最佳方式--嗯,这是一个相当大胆的说法!让我解释一下。
很难说反对测试你的代码,但你不必遵循TDD来做这件事。例如,你可以先写所有的生产代码,然后再写所有的测试。或者,你也可以完全跳过写测试,而是手动测试你的代码。为什么TDD比这些选项更好?
好的测试可以确保你的应用程序按预期运行。然而,不是所有的测试都是好的。为了有测试而写测试并不是一个有价值的工作。相反,好的测试是可以失败的、可重复的、快速运行的和可维护的。
TDD提供方法论,确保你的测试是好的:
- 第一步是写一个失败的测试。根据定义,这证明了测试可以失败。不能失败的测试是没有用的。相反,他们浪费了宝贵的
CPU时间。 - 在你被允许写一个新的测试之前,所有以前的测试必须通过。这确保了你的测试是可重复的。你不只是运行你正在编写的单个测试,而是不断地运行所有的测试。
- 通过频繁地运行每个测试,你有动力确保测试的快速运行。你所有的测试都应该在几秒钟内运行--最好是一秒钟或更少。
一个需要一百毫秒的测试是太慢了。在只有十个测试之后,你的整个测试套件将需要一秒钟的时间来运行。在五十个测试之后,需要五秒。几秒钟后,没有人运行所有的测试,因为它需要太长的时间。
- 当你重构的时候,你同时更新你的生产和测试代码。这可以确保你的测试得到维护。你不断地保持它们的更新。
- 通过迭代编写生产代码和测试并行,你确保你的代码是可测试的。如果你在完成代码后再写测试,那么生产代码很可能需要做很多修改才能完成单元测试。
尽管如此,你心中的魔鬼代言人可能会说,"但你可以不按照TDD来写好的测试"。你肯定可以,但你可能很难成功。你肯定可以在短期内做到这一点,但从长期来看,这要困难得多。你需要有纪律地写好测试。不久之后,你可能会创建某种系统来确保你写出好的测试......你可能会发现自己在做TDD的一个变种!
你应该测试什么?¶
更好的测试覆盖率并不总是意味着你的应用程序被更好地测试。有些事情你应该测试,有些则不应该。以下是该做的和不该做的:
- 为那些不能以自动化方式捕获的代码编写测试。这包括你的类方法中的代码,自定义的
getters和setters,以及你自己编写的大部分其他东西。 - 不要为生成的代码写测试。例如,为生成的
getters和setters写测试是不值得的。Swift在这方面做得很好,你可以相信它的作用。 - 不要为那些可以被编译器捕获的问题写测试。如果测试的问题会产生一个错误或警告,
Xcode会帮你抓住它。 - 不要为依赖性代码编写测试,例如你的应用程序使用的第一或第三方框架。框架的作者负责编写这些测试。例如,你不应该为
Foundation的核心类写测试,因为苹果的开发者负责写这些。然而,你应该为你的自定义子类写测试。这是你的自定义代码,所以你要负责写测试。
上述情况的一个例外是编写测试,以确定一个框架如何工作。这样做可能非常有用。然而,你不需要长期保留这些测试。相反,你应该在事后删除它们。
另一个例外是"理智测试",证明第三方代码按照你的期望工作。如果库不完全稳定,或者你不完全信任它,这类测试就很有用。在这两种情况下,你都应该仔细检查你是否想使用这个库--是否有更好的选择,更值得信赖?
但TDD需要太长的时间!¶
对TDD最常见的抱怨是它花的时间太长了--通常会在后面加上感叹号或愁眉苦脸的表情符号。
幸运的是,一旦你习惯了这样做,TDD就会变快。然而,事实是,与不写任何测试相比,你最终会写更多的代码。最初很可能需要多花一点时间来开发。
也就是说,这个论点有一个非常大的漏洞。开发的真正时间成本并不仅仅是编写最初的、第一版的生产代码。它还包括随着时间的推移增加新的功能,修改现有的代码,修复错误等等。从长远来看,遵循TDD比不遵循TDD所花费的时间要少得多,因为它产生了更多的可维护的代码,而且bug更少。
还有另一个成本需要考虑:生产中的错误对客户的影响。一个问题不被发现的时间越长,它的成本就越高。它可能会导致负面评论,失去信任和收入损失。
如果一个问题在开发过程中被发现,它更容易调试,也更快修复。如果你在几周后才发现这个问题,你就会花费更多的时间来提高代码的速度和追踪根本原因。通过遵循TDD,你的测试最终有助于保障和保护你的应用程序免受错误的影响。
你应该何时使用TDD?¶
TDD可以在产品生命周期的任何时候使用:新的开发、遗留的应用以及两者之间的一切。然而,你如何以及在哪里开始TDD确实取决于你的项目的状态。本书将介绍如何处理许多这种情况!
然而,要问的一个重要问题是:你的项目到底应不应该使用TDD?
作为一个一般的经验法则,如果你的应用程序将持续几个月以上,将有多个版本和/或需要复杂的逻辑,你很可能使用TDD比不使用更好。
如果你是为黑客马拉松、测试项目或其他临时性的东西而创建一个应用,你应该评估TDD是否有意义。如果真的只有一个版本的应用程序,你可能不遵循TDD,或者只对关键或困难的部分进行TDD。
归根结底,TDD是一种工具,由你来决定什么时候使用它是最好的。
关键点¶
在本章中,你了解了什么是TDD,为什么要使用它,要测试什么以及何时使用它。以下是需要记住的关键点:
TDD提供了一个一致的方法来编写好的测试。- 好的测试是可以失败的、可重复的、快速运行的和可维护的。
- 为你负责维护的代码写测试。不要测试自动生成的代码或依赖关系中的代码。
- 开发的真正成本包括最初的编码时间,随着时间的推移增加新的功能,修改现有的代码,修复错误等等。
TDD减少了维护成本和bug的数量,往往使它成为最具成本效益的方法。 TDD对于持续时间超过几个月或有多个版本的长期项目最有用。