从这个概念
开始:1)从您想要的行为开始。为此编写一个测试。查看测试失败。
2)编写足够的代码以使测试通过。查看所有测试通过。
3)查找冗余/草率代码->重构。看到测试仍然通过。转到1
因此,在#1上,假设您要创建一个新命令(我正在扩展该命令的工作方式,所以请耐心等待)。(此外,我会有点务实而不是极端的TDD)
新命令称为MakeMyLunch,因此您首先创建一个测试以将其实例化并获取命令名称:
@Test
public void instantiateMakeMyLunch() {
ICommand command = new MakeMyLunchCommand();
assertEquals("makeMyLunch",command.getCommandName());
}
这将失败,迫使您创建新的命令类并使其返回其名称(纯粹主义者会说这是两回合的TDD,而不是1)。因此,您可以创建该类并使其实现ICommand接口,包括返回命令名称。现在,运行所有测试将显示所有通过,因此您可以继续寻找重构机会。可能没有。
因此,接下来您希望它实现执行。因此,您必须问:我如何知道“ MakeMyLunch”成功“制作了我的午餐”。由于此操作,系统会发生什么变化?我可以对此进行测试吗?
假设很容易测试:
@Test
public void checkThatMakeMyLunchIsSuccessful() {
ICommand command = new MakeMyLunchCommand();
command.execute();
assertTrue( Lunch.isReady() );
}
在其他时候,这更困难,而您真正想做的是测试被测对象的职责(MakeMyLunchCommand)。MakeMyLunchCommand的职责可能是与Fridge和Microwave交互。因此,要进行测试,您可以使用模拟冰箱和模拟微波。[两个示例模拟框架是Mockito和nMock或在这里查看。]
在这种情况下,您将执行以下伪代码:
@Test
public void checkThatMakeMyLunchIsSuccessful() {
Fridge mockFridge = mock(Fridge);
Microwave mockMicrowave = mock(Microwave);
ICommand command = new MakeMyLunchCommand( mockFridge, mockMicrowave );
command.execute();
mockFramework.assertCalled( mockFridge.removeFood );
mockFramework.assertCalled( microwave.turnon );
}
纯粹主义者说测试您班级的责任-它与其他班级的互动(命令是否打开了冰箱并打开了微波炉?)。
实用主义者说,要测试一组课程并测试结果(您的午餐准备好了吗?)。
找到适合您系统的合适平衡。
(注意:考虑到您可能还为时过早。也许您可以在编写单元测试和实现时让它发展,并在步骤3中“注意到”常见的接口机会)。