测试驱动开发
Read in~4 min
Written by - kok-s0s
Mercury 项目采用非常短的(半天)、严格限制的迭代周期。开发团队对所有更改进行了技术审查,并且,有趣的是,引用了 “极限编程中的测试优先于开发” 的理念,在每次微小改动之前进行计划和编写单元测试。--- Craig Larman and Victor R. Basili, Iterative and Incremental Development:A Brief History.IEEE, 2003
普通的旧单元测试的缺点
一套单元测试基本上要比没有测试的要好得多。但是在许多项目中,单元测试的编写与实现的代码是并行的,有时甚至在完成需要开发的模块之后才编写。即普通旧单元测试(POUT)。基本上,POUT 意味着软件是 “代码优先”,而不是测试优先。
其缺点:
- 之后没有必要编写单元测试。一旦一个功能工作(或者看起来能工作),用单元测试改进代码的动机很少。这是没有乐趣的,而且对于很多开发者来说,继续做下一件事情的诱惑力更大。
- 结果代码很难测试。通常情况下,用单元测试改进现有代码并不容易,因为原始代码的可测试性不被重视。这会导致紧耦合的代码出现。
- 通过改进的单元测试达到较高的测试覆盖率并不容易。完成代码后编写单元测试可能会导致漏掉某些问题或者 bug。
测试驱动开发作为颠覆者
测试驱动开发彻底颠覆了传统开发,对于还没有处理过 TDD 的开发人员来说,这种方法代表着思考方法的转变。
TDD 开发在编写相关的产品代码之前一定要先编写测试代码。严格按照步骤执行:当编写完成每个测试后,只编写足以让测试通过的产品代码,直到所有的模块需求开发结束。
TDD 的流程
TDD 的流程通常包括以下几个步骤:
- 编写测试用例
- 运行测试用例
- 编写代码
- 再次运行测试用例
- 重构代码
- 重复以上步骤,直到所有测试用例都通过为止。
TDD 是一种迭代式的开发方法,通过编写测试用例来指导代码的开发和重构,以提高代码的可靠性和质量。关键在于编写清晰、具体和可执行的测试用例,以及持续地运行测试用例并及时修复问题。
当测试百分百通过时,这一事实会给开发者莫大的力量!有了这个无漏洞的单元测试安全网,开发者可以进行无所畏惧的重构。代码的坏味道(例如重复的代码)或者设计问题现在可以修复了。不必害怕破坏功能,因为定期执行的单元测试会立即给我们反馈。令人高兴的是:如果一个或多个测试在重构阶段失败,导致这一结果的代码更改会非常小。
BOB 叔叔关于 TDD 的三大原则:
- 除非为了使一个失败的单元测试通过,否则不允许编写任何产品代码。
- 在一个单元测试中只允许编写刚好能够导致失败的代码 --- 编译错误也算失败。
- 只允许编写刚好能够使一个失败的单元测试通过的产品代码。
TDD 的优势
测试驱动开发(TDD)主要适用于软件组件增量设计和开发的工具和技术。
优势:
- 如果遵循 TDD 的思想,在开发时就会逐步完成你的需求
- TDD 建立了一个非常快速的反馈循环
- 先编写单元测试有助于开发人员思考接下来应该做什么
- 在 TDD 的帮助下,无间隙的规范以可执行代码的形式出现
- 开发人员能够更加自觉和负责任地处理依赖关系
- 通常情况下,利用 TDD 开发的新产品代码将具有 100% 的单元测试覆盖率
什么时候不应该使用 TDD
原型设计 - 不建议
框架、库、技术或架构模式的基本决策 - 不管用