TDD从何开始
作者:网络转载 发布时间:[ 2012/6/25 10:50:25 ] 推荐标签:
对应的outputPrinter可以做如下的微调:
public class OutputPrinter {
public void print(String result) {
}
}
后别忘了启动Expectation验证:
context.assertIsSatisfied();
整个测试方法现在看起来应该是这样的:
@Test
public void should_play_game_and_win() {
Mockery context = new JUnit4Mockery() {
{
setImposteriser(ClassImposteriser.INSTANCE);
}
};
final AnswerGenerator answerGenerator = context.mock(AnswerGenerator.class);
final InputCollector inputCollector = context.mock(InputCollector.class);
final Guesser guesser = context.mock(Guesser.class);
final OutputPrinter outputPrinter = context.mock(OutputPrinter.class);
context.checking(new Expectations() {
{
one(answerGenerator).generate();
will(returnValue("1234"));
}
{
one(inputCollector).guess();
will(returnValue("1234"));
}
{
oneOf(guesser).verify(with(equal("1234")), with(equal("1234")));
will(returnValue("4A0B"));
}
{
oneOf(outputPrinter).print(with(equal("You win")));
}
});
Game game = new Game(answerGenerator, inputCollector, guesser, outputPrinter);
game.start();
context.assertIsSatisfied();
}
运行测试,会看到下面的错误信息:
java.lang.AssertionError: not all expectations were satisfied
expectations:
expected once, never invoked: answerGenerator.generate(); returns "1234"
expected once, never invoked: inputCollector.guess(); returns "1234"
expected once, never invoked: guesser.verify("1234"); returns "4A0B"
expected once, never invoked: outputPrinter.print("You win"); returns a default value
at org.jmock.lib.AssertionErrorTranslator.translate(AssertionErrorTranslator.java:20)
at org.jmock.Mockery.assertIsSatisfied(Mockery.java:196)
at com.swzhou.tdd.guess.number.GameFacts.should_play_game_and_win(GameFacts.java:54)
太好了,正是我们期望的错误!别忘了我们只是在测试中定义了期望的游戏流程,真正的game.start()还是空的呢!现在让测试指引着我们前行吧。
先改一改我们的Game类,把需要依赖的协作对象作为Game的字段:
private AnswerGenerator answerGenerator;
private InputCollector inputCollector;
private Guesser guesser;
private OutputPrinter outputPrinter;
public Game(AnswerGenerator answerGenerator, InputCollector inputCollector, Guesser guesser, OutputPrinter outputPrinter) {
this.answerGenerator = answerGenerator;
this.inputCollector = inputCollector;
this.guesser = guesser;
this.outputPrinter = outputPrinter;
}
然后在start方法中通过answerGenerator来产生一个4位数:
public void start() {
String answer = answerGenerator.generate();
}
再跑测试,会发现仍然错,但结果有变化,第一步已经变绿了!
java.lang.AssertionError: not all expectations were satisfied
expectations:
expected once, already invoked 1 time: answerGenerator.generate(); returns "1234"
expected once, never invoked: inputCollector.guess(); returns "1234"
expected once, never invoked: guesser.verify("1234"); returns "4A0B"
expected once, never invoked: outputPrinter.print("You win"); returns a default value
at org.jmock.lib.AssertionErrorTranslator.translate(AssertionErrorTranslator.java:20)
at org.jmock.Mockery.assertIsSatisfied(Mockery.java:196)
at com.swzhou.tdd.guess.number.GameFacts.should_play_game_and_win(GameFacts.java:54)
下面应该使用inputCollector来收集玩家的输入:
public void start() {
String answer = answerGenerator.generate();
String guess = inputCollector.guess();
}
跑测试,错但是结果进一步好转,已经有两步可以通过了:
java.lang.AssertionError: not all expectations were satisfied
expectations:
expected once, already invoked 1 time: answerGenerator.generate(); returns "1234"
expected once, already invoked 1 time: inputCollector.guess(); returns "1234"
expected once, never invoked: guesser.verify("1234"); returns "4A0B"
expected once, never invoked: outputPrinter.print("You win"); returns a default value
at org.jmock.lib.AssertionErrorTranslator.translate(AssertionErrorTranslator.java:20)
at org.jmock.Mockery.assertIsSatisfied(Mockery.java:196)
at com.swzhou.tdd.guess.number.GameFacts.should_play_game_and_win(GameFacts.java:54)
下面加快节奏,按照测试中的需求把剩下的流程走通吧:
public void start() {
String answer = answerGenerator.generate();
String guess = inputCollector.guess();
String result = "";
do {
result = guesser.verify(guess, answer);
} while (result != "4A0B");
outputPrinter.print("You win");
}
再跑测试,啊哈,终于看到那个久违的小绿条了!
回顾一下这一轮从无到有、测试从红到绿的小迭代,我们终的产出是:
1、一个可以用来描述游戏流程的测试(需求,文档?)。
2、由该需求推出的一个流程骨架(Game.start)。
3、一堆基于该骨架的协作类,虽然是空的,但它们每个的职责是清晰的。
经过这艰难的第一步(实际上叙述的过程比较冗长,但反馈周期还是很快的),相信每个人都会对完整实现这个游戏建立信心,并且应该知道后面的步骤要怎么走了吧。是的,我们可以通过写更多的骨架测试来进一步完善它(比如考虑失败情况下的输出,增加对用户输入的验证等等),或者深入到每个小协作类中,继续以TDD的方式实现每一个协作类了。无论如何,骨架已在,我们是不大可能出现大的偏差了。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11