Warum TDD nicht „Tests schreiben“ bedeutet, sondern „anders denken“
\n\nStellen Sie sich vor, Sie bauen ein Haus. Sie haben Baupläne, Material und ein Team. Aber Sie beginnen mit dem Mauern, ohne das Fundament geprüft zu haben. Einen Monat später stellen Sie fest, dass die Wände Risse bekommen. Kommt Ihnen bekannt vor? In der Programmierung nennt man das „das reparieren wir später“. Und „später“ ist meist um 3 Uhr morgens kurz vor dem Deployment.
\n\nTestgetriebene Entwicklung (TDD — Test-Driven Development) ist eine Technik, die den Prozess auf den Kopf stellt. Sie schreiben nicht erst den Code und dann die Tests. Sie schreiben zuerst den Test – und erst dann den Code, der diesen Test besteht. Klingt verrückt? In der Praxis spart das Stunden, Nerven und macht den Code sauberer als die Morgenluft in den Bergen.
\n\nIn diesem Artikel betrachten wir TDD in Java an konkreten Beispielen. Kein überflüssiges Gerede – nur Code, der Red-Green-Refactor-Zyklus und reale Szenarien. Los geht's.
\n\nWas ist TDD und wie funktioniert der Red-Green-Refactor-Zyklus
\n\nTDD basiert auf drei einfachen Schritten, die sich zyklisch wiederholen:
\n\n- \n
- Red — Wir schreiben einen Test, der nicht bestanden wird (er muss fehlschlagen). \n
- Green — Wir schreiben minimalen Code, damit der Test bestanden wird. \n
- Refactor — Wir verbessern den Code, ohne sein Verhalten zu ändern. Die Tests bleiben dabei grün. \n
Es scheint, als würde das die Entwicklung verlangsamen. In Wirklichkeit beschleunigt es sie. Sie hören auf zu raten, „funktioniert das eigentlich?“. Sie wissen: Es funktioniert, weil der Test grün ist.
\n\nDie wichtigsten Prinzipien von TDD
\n- \n
- Schreiben Sie keine einzige Zeile Produktionscode ohne einen Test. \n
- Der Test sollte so einfach wie möglich sein und genau ein Verhalten prüfen. \n
- Der Code wird genau so weit geschrieben, dass der Test bestanden wird. Kein „ach, fügen wir das auch noch für alle Fälle hinzu“. \n
Kommen wir nun zu Java und JUnit 5 – dem beliebtesten Framework für Modultests.
\n\nProjekt-Setup: Maven, JUnit 5 und die Struktur
\n\nFür die Beispiele verwenden wir Maven. Fügen Sie die folgende Abhängigkeit in Ihre pom.xml ein:
<dependency>\n <groupId>org.junit.jupiter</groupId>\n <artifactId>junit-jupiter-api</artifactId>\n <version>5.10.0</version>\n <scope>test</scope>\n</dependency>\n\nDie Ordnerstruktur ist der Maven-Standard:
\nsrc/\n main/java/com/example/\n test/java/com/example/\n\nAlle Testklassen legen wir in src/test/java. Der Name der Testklasse stimmt in der Regel mit dem Namen der zu testenden Klasse überein, plus dem Suffix Test. Zum Beispiel Calculator → CalculatorTest.
Erster TDD-Zyklus: Einen Taschenrechner von Grund auf schreiben
\n\nAufgabe: Erstellen Sie eine Methode add(int a, int b), die die Summe zurückgibt. Nach TDD beginnen wir nicht mit der Klasse, sondern mit dem Test.
Schritt 1: Red — Einen Test schreiben, der fehlschlägt
\n\nimport org.junit.jupiter.api.Test;\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CalculatorTest {\n\n @Test\n void shouldAddTwoNumbers() {\n Calculator calc = new Calculator();\n int result = calc.add(2, 3);\n assertEquals(5, result);\n }\n}\n\nWir versuchen, den Test auszuführen – der Compiler meckert: Die Klasse Calculator existiert nicht. Perfekt, die rote Lampe leuchtet.
Schritt 2: Green — Minimalen Code schreiben
\n\nWir erstellen die Klasse Calculator mit einer Methode, die einfach die Summe zurückgibt:
public class Calculator {\n public int add(int a, int b) {\n return a + b;\n }\n}\n\nWir führen den Test aus – grün. Die minimal mögliche Implementierung hat funktioniert.
\n\nSchritt 3: Refactor
\n\nAn diesem Punkt ist der Code bereits einfach, es gibt nichts zu refaktorisieren. Aber stellen wir uns vor, wir möchten die Methode umbenennen oder eine Überlaufprüfung hinzufügen. Wir tun dies, und der Test besteht immer noch. Wenn etwas kaputt geht – der Test wird fehlschlagen und sofort auf das Problem hinweisen.
\n\n