测试驱动开发-2

2. 变质的对象

测试驱动开发的总体流程如下:

  1. 写一个测试程序。
  2. 让测试程序运行。
  3. 编写合格的代码。

计划清单(to-do list)

当瑞士法郎与美元的兑换率为 2:1 的时候,5 美元 + 10 瑞士法郎 = 10 美元

5 美元 * 2 = 10 美元

将 "amount" 定义为私有

Dollar 类有副作用吗?

钱数必须为整数?

在 Dollar 对象上施加一个操作后,Dollar 对象改变了。假设代码是:

public void testMultiplication() {
    Dollar five = new Dollar(5);
    five.times(2);
    assertEquals(10, five.amount);
    five.times(3);
    assertEquals(15, five.amount);
}

第一次调用 times() 函数后,five 已经不再是 5 了,它实际上是 10。如果我们从 times() 函数返回一个新对象,那么我们可以多次对原来的 five 进行操作,但不会让它发生丝毫变化。

public void testMultiplication() {
    Dollar five = new Dollar(5);
    Dollar product = five.times(2);
    assertEquals(10, product.amount);
    five.times(3);
    assertEquals(15, product.amount);
}

改变 Dollar.times() 函数声明,让新的测试程序编译通过。

Dollar times(int multiplier) {
    amount *= multiplier;
    return null;
}

测试程序可以编译了,但无法运行。需要返回一个新的带有正确的 amount 值的 Dollar 对象:

Dollar times(int multiplier) {
    return new Dollar(amount * multiplier);
}

测试程序运行通过,下面是尽快使测试程序可运行的三条策略:

  • 伪实现——返回一个常量并逐渐用变量替代常量,直至伪实现代码成为真实实现的代码
  • 显明实现(Obvious Implementation)——将真实的实现代码键入
  • 三角法(Triangulation)——当例子达到 2 个或更多时才对代码实施一般化

本章工作回顾:

  • 将一个设计缺陷(副作用)转化为一个由此缺陷导致运行失败的测试程序。
  • 采用存根实现使代码迅速编译通过。
  • 键入我们认为正确的代码使测试程序尽快工作。

测试驱动开发-2

上一篇:ModelAndView和ModelMap的区别


下一篇:React项目启动时,报错createProxyMiddleware is not a function