À partir de ce concept:
1) Commencez par le comportement que vous désirez. Écrivez un test pour cela. Voir échec du test.
2) Écrivez suffisamment de code pour réussir le test. Voir tous les tests réussis.
3) Recherchez le code redondant / bâclé -> refactor. Voir les tests réussissent toujours. Goto 1
Donc, sur # 1, disons que vous voulez créer une nouvelle commande (je m'étends sur la façon dont la commande fonctionnerait, alors restez avec moi). (De plus, je serai un peu pragmatique plutôt que TDD extrême)
La nouvelle commande est appelée MakeMyLunch, vous devez donc d'abord créer un test pour l'instancier et obtenir le nom de la commande:
@Test
public void instantiateMakeMyLunch() {
ICommand command = new MakeMyLunchCommand();
assertEquals("makeMyLunch",command.getCommandName());
}
Cela échoue, vous obligeant à créer la nouvelle classe de commandes et à lui faire retourner son nom (puriste dirait que c'est deux tours de TDD, pas 1). Vous créez donc la classe et lui faites implémenter l'interface ICommand, y compris en renvoyant le nom de la commande. L'exécution de tous les tests montre maintenant que tous les tests ont réussi, vous devez donc rechercher des opportunités de refactoring. Probablement aucun.
Ensuite, vous voulez qu'il implémente l'exécution. Il faut donc se demander: comment savoir si "MakeMyLunch" a "réussi mon déjeuner". Quels changements dans le système à cause de cette opération? Puis-je tester cela?
Supposons qu'il soit facile de tester:
@Test
public void checkThatMakeMyLunchIsSuccessful() {
ICommand command = new MakeMyLunchCommand();
command.execute();
assertTrue( Lunch.isReady() );
}
D'autres fois, c'est plus difficile, et ce que vous voulez vraiment faire, c'est tester les responsabilités du sujet à tester (MakeMyLunchCommand). Peut-être que la responsabilité de MakeMyLunchCommand est d'interagir avec le réfrigérateur et le micro-ondes. Donc, pour le tester, vous pouvez utiliser un faux réfrigérateur et un faux micro-ondes. [deux exemples de frameworks simulés sont Mockito et nMock ou regardez ici .]
Dans ce cas, vous feriez quelque chose comme le pseudo-code suivant:
@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 );
}
Le puriste dit tester la responsabilité de votre classe - ses interactions avec les autres classes (la commande a-t-elle ouvert le réfrigérateur et allumé le micro-ondes?).
Le pragmatiste dit de tester un groupe de classes et de tester le résultat (votre déjeuner est-il prêt?).
Trouvez le bon équilibre qui fonctionne pour votre système.
(Remarque: considérez que vous êtes peut-être arrivé à votre structure d'interface trop tôt. Peut-être pouvez-vous laisser cela évoluer lorsque vous écrivez vos tests unitaires et implémentations, et à l'étape 3, vous "remarquez" l'opportunité d'interface commune).