Denken Sie, dass Sie TDD gut beherrschen, weil Sie es schon seit Jahren tun? Das dachte ich auch, bis ich eine Übung namens "TDD as if you mean it" gemacht habe, die mich wieder auf den Boden der Tatsachen gebracht hat!
Bei zwei verschiedenen TDD-Workshops habe ich versucht, eine Anwendung nach den Regeln von "TDD as if you mean it" zu erstellen. Das erste Mal war in Amsterdam bei einem Coderetreat und das zweite Mal bei einer XKE-Sitzung bei Xebia. Obwohl ich TDD schon seit einer Weile praktiziere, war das Ergebnis der Übungen in beiden Sitzungen, dass ich nur wenige Tests, noch weniger Produktionscode und eine Anwendung hatte, die nicht funktionierte.
TDD als ob Sie es ernst meinen
TDD selbst ist ein recht einfacher Prozess. Kent Becks Beschreibung eines einzelnen TDD-Zyklus lautet:- Fügen Sie einen kleinen Test hinzu
- Alle Tests ausführen und fehlschlagen
- Verändern Sie etwas
- Führen Sie die Tests durch und haben Sie Erfolg
- Umstrukturierung zur Beseitigung von Doppelarbeit
- Weiter zu (1)
- Schreiben Sie genau einen fehlgeschlagenen Test
- Machen Sie den Test aus (1) erfolgreich, indem Sie zuerst den Implementierungscode in den Test selbst schreiben.
- Erstellen Sie eine neue Implementierungsmethode/Funktion durch:
- Ausführen von "extract method" für den gemäß (2) erstellten Implementierungscode oder
- Verschieben von Implementierungscode gemäß (2) in eine bestehende Implementierungsmethode
- Erstellen Sie nur neue Methoden in der Testklasse
- Erstellen Sie nur Implementierungsklassen, die ein Ziel für die Extraktion einer gemäß (4) erstellten Methode bieten.
- Befüllen Sie die Implementierungsklassen, indem Sie eine "move method" von einer Testklasse in die Implementierungsklassen übertragen.
- Refactor
- Weiter zu (1)
Die Übung
Bei einem XKE bei Xebia mussten wir eine Enigma-Maschine bauen. Wir bekamen eine Beschreibung auf Papier, wie die Enigma-Maschine funktioniert und wie die verschiedenen Teile wie die Rotoren und der Reflektor für ein bestimmtes Verhalten verantwortlich sind. Mein Partner und ich einigten uns darauf, "TDD so zu machen, als ob Sie es ernst meinen", also schrieben wir unseren ersten Test und dann steckten wir fest. Wir starrten auf den Bildschirm und fingen an, über die verschiedenen Teile einer Enigma-Maschine zu diskutieren, aber darum ging es bei dieser Übung nicht. Wir sollten uns von der Idee verabschieden, dass die Domäne Rotoren und einen Reflektor haben muss und unsere Tests das Design und die Domäne bestimmen lassen. Außerdem konnten wir nicht sehen, wie sich die ersten einfachen Tests zu einer funktionierenden Enigma-Maschine entwickeln würden. Mit Hilfe eines der Moderatoren schrieben wir einige weitere Tests, aber wir verstrickten uns oft in Diskussionen über Rotoren und den Reflektor. Die nächsten TDD-Zyklen werden Ihnen eine Vorstellung davon vermitteln, warum mein Partner und ich der Meinung waren, dass die ersten Tests sinnlos waren und nicht in eine funktionierende Enigma-Maschine münden konnten. Sie werden auch sehen, wie sich der Code nach nur wenigen Zyklen weiterentwickelt. [java title="Zyklus 1 - ein Zeichen übersetzen"] @Test public void shouldTranslateCharacter() throws Exception { assertThat(translate("A"), is("T")); } private String translate(String input) { if ("A".equals(input)) { return "T"; } return ""; } [/java] [java title="Zyklus 2 - zweites Zeichen übersetzen"] @Test public void shouldTranslateCharacter() throws Exception { assertThat(translate("A"), is("T")); assertThat(translate("B"), is("S")); } private String translate(String input) { if ("A".equals(input)) { return "T"; } else if ("B".equals(input)) { return "S"; } return ""; } [/java] [java title="Zyklus 3 - Drittes Zeichen übersetzen"] @Test public void shouldTranslateCharacter() throws Exception { assertThat(translate("A"), is("T")); assertThat(translate("B"), is("S")); assertThat(translate("C"), is("N")); } private String translate(String input) { if ("A".equals(input)) { return "T"; } else if ("B".equals(input)) { return "S"; } else if ("C".equals(input)) { return "N"; } return ""; } [/java] [java title="Zyklus 3 - nach dem Refactoring"] @Test public void shouldTranslateCharacter() throws Exception { assertThat(translate("A"), is("T")); assertThat(translate("B"), is("S")); assertThat(translate("C"), is("N")); } private String translate(String input) { Map<String, String> alphabet = new HashMap<String, String>(); alphabet.put("A", "T"); alphabet.put("B", "S"); alphabet.put("C", "N"); return alphabet.get(input); } [/java] Die Methode translate in den Tests übersetzt das eingegebene Zeichen in ein verschlüsseltes Zeichen. Dies ist das Verhalten, das dem Verhalten eines Rotors oder sogar der gesamten Enigma-Maschine ähnelt. Sie könnten sich vorstellen, dass die translate-Methode irgendwann in eine Translator-Klasse statt in eine Rotor-Klasse wandert. Was Sie tun werden, ist, dass Sie Methoden mit gemeinsamem Verhalten in eine einzige Klasse packen und das bringt uns zu einer der grundlegenden Ideen der Domänenmodellierung von Eric Evans, dass die besten Modelle nicht die realistischsten sind, sondern die, die es uns erlauben, ein bestimmtes Problem effizient zu beschreiben. Wie ich bereits erwähnt habe, hatten wir am Ende des XKE nur ein paar Tests und noch weniger Produktionscode, aber wir haben einige wertvolle Dinge gelernt.Was ich gelernt habe
Nach zwei TDD-Sitzungen, in denen ich die Regeln von "TDD as if you mean it" befolgt habe, habe ich gelernt:- Es ist schwer, die Domäne loszulassen, in diesem Fall die Rotoren und den Reflektor, und die Tests das Design und die Domäne bestimmen zu lassen. Am Anfang dachte ich, dass ich einen Rotor oder Reflektor brauchen würde, sonst könnte ich keinen Test schreiben und ich wusste, dass ich einen Rotor brauchte.
- Die ersten Tests erscheinen sinnlos, weil Sie in kleinen Schritten vorgehen. Sie erhalten zum Beispiel Tests wie 1 == 2, die Sie in der Testklasse korrigieren.
- Der Produktionscode, den ich geschrieben habe, war sehr "sauber". Das bedeutet kleine Methoden mit nur einer Verantwortung (SRP).
Verfasst von
Arjan Wulder
Unsere Ideen
Weitere Blogs
Contact
Let’s discuss how we can support your journey.



