作者:Andrew Trenk
原文链接:http://googletesting.blogspot.tw/2013/08/testing-on-toilet-test-behavior-not.html
Calculator类是最流行的开源项目之一,很多用户喜欢使用:
publicclass Calculator {
publicintadd(inta, intb) {
returna + b;
}
}
为确保它能正常工作,还需要对它进行测试:
publicvoidtestAdd() {
assertEquals(3, calculator.add(2, 1));
assertEquals(2, calculator.add(2, 0));
assertEquals(1, calculator.add(2, -1));
}
可是,你发现一个很棒的新库(Library),使用它代替加法操作符,可以保证编码的速度提高几个数量级。于是你很兴奋地更改你的代码,去使用这个库:
publicclass Calculator {
private AdderFactory adderFactory;
public Calculator(AdderFactor adderFactory) { this.adderFactory = adderFactory; }
publicintadd(inta, intb) {
Adder adder = adderFactory.createAdder();
ReturnValue returnValue = adder.compute(new Number(a), new Number(b));
returnreturnValue.convertToInteger();
}
}
这很容易,但对于这段代码,你会怎么去测试呢?其实现已存在的测试用例应该没有必要做更改,因为你只改变了代码的实现方式,并没有改变面向用户的行为。在大多数情况下,测试用例更应该着重测试代码公共的API,而不需要去考虑代码实现的细节。
当测试用例独立于实现细节时,更容易去维护。因为每次实现的代码变化后,它们是不需要做任何更改的。同时它们也更容易理解,因为它们基本上可以作为代码示例,来展示所有不同的方式去调用这个类的方法。所以即使有人对方法的实现方式不熟悉,也可以通过阅读这些测试用例来了解如何使用该类。
在很多情况下,你会想要去测试具体的实现细节(例如,你要确认读取的数据是从缓存中读取,而不是从数据存储中),但这应该要很少出现。因为大多数情况下,测试用例应该独立于实现方式。
需要注意的是,如果实现方式改变了,测试用例可能也需要进行更改(例如,如果你在构造函数中新添加了个依赖,那么在测试时,需要通过这种依赖性去创建这个类)。如果代码的面向用户的行为并没有改变,实际的测试用例也就不需要改变。