TDD – 它在更大质量框架中的位置

在这一部分,我们将批判性地审视 TDD 为测试带来了什么,以及哪些仍然是需要人工参与的活动。虽然 TDD 作为测试策略的一部分无疑具有优势,但它永远不能成为成功软件系统的全部策略。

理解 TDD 的局限性

就主流开发而言,TDD(测试驱动开发)是一门相对较新的学科。现代 TDD 的起源可以追溯到 Kent Beck 在克莱斯勒综合薪酬系统(Chrysler Comprehensive Compensation System)中的工作(详见进一步阅读部分,测试优先的单元测试理念即源于此)。该项目始于 1993 年,Kent Beck 于 1996 年加入。

克莱斯勒综合薪酬项目的特点是广泛使用单元测试来驱动小迭代和频繁的代码发布。希望我们能从本书前面的章节中识别出这些理念。自那时以来,许多事情发生了变化——部署选项不同了,用户数量增加了,敏捷方法更加普遍——但测试的目标仍然相同。这些目标是驱动出正确、良好设计的代码,并最终满足用户需求。

测试自动化的替代方案是在没有自动化的情况下运行测试——换句话说,手动运行测试。更好的术语可能是“人工驱动”。在测试自动化普及之前,任何开发计划的重要组成部分都是测试策略文档。这些冗长的文档定义了何时进行测试、如何进行测试以及由谁进行测试。这些策略文档与详细的测试计划并存。这些测试计划也是书面文档,描述了要执行的每个测试——如何设置、具体测试哪些步骤以及预期结果是什么。传统的瀑布式项目会花费大量时间来定义这些文档。在某些方面,这些文档类似于我们的 TDD 测试代码,只是写在纸上,而不是源代码中。

执行这些手动测试计划是一项巨大的工作。运行测试需要我们手动设置测试数据,运行应用程序,然后点击用户界面。结果必须记录下来。发现的缺陷必须记录在缺陷报告中。这些报告必须反馈到瀑布流程中,触发重新设计和重新编码。这必须在每次发布时都进行。人工驱动的测试是可重复的,但只有在花费大量时间准备、更新和遵循测试文档的情况下才能实现。所有这些都需要时间——而且是大量的时间。

在这种背景下,Beck 的 TDD 理念显得非常引人注目。测试文档变成了可执行的代码,可以按需运行,成本仅为人工测试的一小部分。这是一个引人注目的愿景。测试代码的责任现在成为开发者工作的一部分。测试本身就是源代码的一部分。这些测试是自动化的,能够在每次构建时全面运行,并随着代码的变化而保持更新。

不再需要手动测试?

人们很容易认为,使用本书中描述的 TDD 可能会消除手动测试。它确实消除了一些手动过程,但肯定不是全部。我们用自动化替代的主要手动步骤是开发过程中的功能测试和发布前的回归测试。

当我们使用 TDD 开发新功能时,我们从为该功能编写自动化测试开始。我们编写的每一个自动化测试都是一个不需要手动运行的测试。我们节省了所有测试设置时间,以及通常需要点击用户界面来触发我们测试行为的冗长过程。TDD 带来的主要区别是用 IDE 中编写的测试代码取代了在文字处理器中编写的测试计划。开发功能的手动测试被自动化取代。

TDD 还为我们提供了免费的自动化回归测试:

image 2025 01 12 17 49 37 920
Figure 1. Figure 11.1 – Regression testing

使用 TDD,我们在构建每个功能时添加一个或多个测试。重要的是,我们保留了所有这些测试。我们自然地构建了一个大型的自动化测试套件,这些测试被捕获在源代码控制中,并在每次构建时自动执行。这被称为回归测试套件。回归测试意味着我们在每次构建时重新检查迄今为止运行的所有测试。这确保我们在对系统进行更改时不会破坏任何东西。快速行动而不破坏东西可能是我们描述这种方法的方式。

回归测试还包括针对先前报告的缺陷的测试。这些回归测试确认这些缺陷没有被重新引入。值得一提的是,回归测试套件在每次执行时都节省了非自动化测试所需的所有手动工作。这在完整的软件生命周期中累积起来,大大减少了工作量。

测试自动化是好的,但自动化测试是一个软件机器。它不能自己思考。它不能直观地检查代码。它不能评估用户界面的外观。它不能判断用户体验是好是坏。它不能确定整个系统是否适合用途。

这就是人工驱动的手动测试发挥作用的地方。接下来的部分将探讨我们需要人工主导测试的领域,从一个显而易见的领域开始:找到我们测试遗漏的缺陷。