理念

  如果我们能够在设计程序前先设计测试方案,情况怎么样?

  如果我们能够做到:除非缺乏某个功能将导致测试失败;否则拒绝在程序中实现该功能,情况会怎么样?

  如果我们能够做到:除非由于缺少某行代码将导致测试失败,否则拒绝在程序中增加哪怕一行代码,情况会怎样?

  如果首先编写失败的测试表明需要一项功能,然后再逐渐地增加那项功能使测试通过,情况又会怎样?

  这对于我们正在编写的软件的设计有什么影响?如果存在这样一组包罗万象的测试,我们能够从中得到什么好处?

  方法

  ● 创建一个清单,列出我们所知道的需要让其运行通过的测试

  ● 通过一小段代码说明我们希望看到怎样的一种操作

  ● 暂时忽略JUnit的一些细节问题

  ● 通过建立存根(stub)来让测试程序通过编译

  ● 通过一些另类的做法来让测试运行通过

  ● 逐渐使工作代码一般化,用变量代替常量

  ● 将新的工作逐步加入计划清单,而不是一次全部提出

  尽快使测试程序可运行的策略

  1、伪实现

  返回一个常量并逐渐用变量代替常量直至伪实现代码成为真正实现的代码。

  2、显明实现

  将真正实现的代码直接敲入。

  3、三角法

  测试的步骤/阶段

  1、写一个测试程序

  2、让测试程序编译通过

  3、运行测试程序,发现不能运行

  4、让测试程序可以运行

  5、消除重复设计,优化设计结构(重构)

  不同的阶段有不同的目的。它们需要不同的解决方式,不同的审美观。前三个阶段需要很快完成,这样我们达到一个包含新功能的已知状态。你可以不择手段地到达这一状态,这是因为在此短暂的一刻尽快地让测试程序运行通过比如何设计更重要。

  虽然在前三阶段,你可以抛弃所有的设计原则,但是,记住,这一开发周期还没有结束。没有第五步,整个周期的前四步也毫无意义。要适时地进行设计。该让它运行通过时让它运行通过,该优化时让要进行优化。

  经过前面三个阶段,可能你的代码充满了很多重复代码和重复设计。请记住,在你编写下一个测试代码之前请把它们清除掉。

  测试驱动开发的过程

  ● 加入一个小的测试

  ● 运行所有的测试,运行失败

  ● 适当修改

  ● 运行测试且成功

  ● 重构,消除重复设计,优化设计结构

  体会

  将设计缺陷转化为测试代码进行证明

  当发现某种情形不该成立或者应该成立时,第一件事情都应该把它变成测试代码,然后证明它(测试不通过)。再修改现有代码以通过测试。

  或者说:

  ● 将一个设计缺陷(副作用)转化为一个由此缺陷导致运行失败的测试程序。

  ● 将采用存根实现使代码迅速编译通过

  ● 键入我们认为正确的代码以使测试程序能尽快工作

  每一次只处理清单上的一个问题

  每一次只解决清单上的一个问题。让测试通过后,要及时进行重构。在未消除重复代码之前,请不要写下一个测试用例。

  有代码,无测试?

  当你增加一行代码,而它没有测试代码时,这个时候你应该停止,然后思考。允许没有测试代码的代码存在么?

  除非由于缺少某行代码将导致测试失败,否则拒绝在程序中增加哪怕一行代码。