测试驱动开发模式的领悟

一、概述

什么是TDD

TDD颠覆了传统的开发和测试。TDD不是先写业务代码,而是先写测试代码,写业务代码来反向满足测试代码的校验。TDD规定你先写测试代码,然后实现代码直到刚刚写的测试代码通过。

TDD的基本思路就是通过测试来推动整个开发的进行,但测试驱动开发并不只是单纯的测试工作,而是把需求分析,设计,质量控制量化的过程。

TDD基本原则

  1. 写测试用例:在实现功能之前先编写测试用例。测试用例描述了要测试的功能,以及预期的输出结果。

  2. 测试失败: 在实现功能之前,测试用例应该无法通过。

  3. 编写最小可行代码:一旦测试用例编写完成并产生了失败结果,程序员应编写最小量的代码以满足测试要求。这样一来,不仅设计的代码会更加精简,而且也会更加容易阅读和维护。

  4. 通过测试:修改代码后,再运行测试用例进行测试。如果代码编写正确,测试用例应该全部通过。如果没有全部通过,程序员必须继续优化代码直到测试完成通过。

  5. 重构代码:该阶段可以考虑进行代码重构,优化的目的是使代码更加简洁、具有更好的可读性和可维护性,不改变程序的功能和行为。

TDD的基本原则是始终让测试来驱动代码的开发。通过编写测试用例,程序员可以始终专注于软件的核心功能,并通过反复测试与重构代码,让软件更加健壮和可读。这样一来,软件质量和可维护性将大大提高。

如何进行TDD

tdd-1

  • 写一个测试(红)

  • 让测试通过(绿)

  • 优化设计(重构)

然后重复这个周期。

二、TDD的工程效能

  1. 为什么要开发人员来写测试?这难道不是测试人员的工作吗?
  2. 开发写了测试,测试人员就不用再测了嘛?
  3. 又要写测试,又要写生产代码,效率是不是太低了?只写生产代码效率应该更高吧?
  4. 不写测试我也能写出可以工作的软件,那么写测试能给我带来什么额外的好处呢?

程序员自测(Developer Testing)

在“正常软件开发模式”中,貌似测试只是最后的验收步骤,程序员很少直接参与。

但事实却不是这样,就算是所谓的“正常软件开发模式”,也有着非常多“程序员测试”的步骤。只不过这些“程序员测试”并不表现为自动化测试,而是由“测试应用”、“跑一下” 和 “Debug”等隐含手段体现的,所谓的程序员自测。

测试应用

所谓“测试应用”并不是某个技巧正式的名字,但是所有人都熟知这一技巧:

  • 构造一个简单的控制台应用(Console Application),并提供 main 入口函数(Entry point);
  • 在 main 函数中,调用所编写的代码,并通过与控制台的交互(各种 println、writeline 之类的函数),将结果输出在控制台上;
  • 再通过观察控制台的输出,判断结果正确与否。

跑一下

从严谨的角度出发,“跑一下”甚至不能算是它真正的名字。它真正的名字应该叫“在我本地的测试环境中跑一下”。

比如:我开发了一个创建接口,我通过postmant调用一下,观察一下数据库是否插入。

Debug

“测试应用”和“跑一下”这两种技巧更多地关注在发现问题上,可以看作是“验证测试”。

而“调试”通常发生在已经明显知道有错误的代码中,是一个定位错误的过程。

So,在软件开发中,一直都存在验证性测试和定位性测试两种测试。

这也很好理解,我们既要知道代码有没有错误,还要知道当错误发生时,错误发生在哪里。 从定位性测试的角度出发,对比这两种做法,从意图上,我们可以粗略地认为,它们是对于同一种意图的两种不同实现:手动的启发式定位 与 有计划的逐模块自动化排查。

TDD的核心逻辑

任何有过编程经验的开发同学,都能根据自己类似的经历,那些年做过的“程序员自测经历”。

我们构造软件的过程,就是通过一系列验证测试(测试应用、跑一下、Debug一下等),证明我们在朝着正确的方向前进;

如果验证的过程中发现出了错误,那么再通过一系列定位测试(调试等),找到问题的根源,加以改进。

tdd-2

现在让我们回到最初的问题:测试驱动开发过分强调测试对于程序员的重要性了吗?答案是:并没有

验证测试与定位测试,本身就贯穿了整个软件构造的过程。测试构成了整个开发流程的骨架,功能开发可以看作填充在测试与测试之间的血肉。

这就是测试驱动开发的核心逻辑:以测试作为切入点,可以提纲挈领地帮助我们把握整个研发的过程。

一个个测试就像一个个里程碑点(Milestone),规划着研发活动的进度。围绕这些里程碑点,我们就可以持续对成本和效率进行管理和改进。测试驱动开发将个体的开发活动,变成了工程化的研发过程。

核心思想领悟

测试驱动开发并不是关于“怎么写测试”、“怎么消除测试人员”、“怎么让开发人员多干一份活”的编码技巧。

它是以测试为里程碑点的工程化研发过程,测试驱动开发将软件流程中无时无处不在的低效测试手段,以可重复的、高效的自动化测试代替,以获得更高的工程效能。 这就是隐藏在测试驱动开发反直觉的工程实践背后的核心逻辑。

0%