Test Driven Development (TDD) ist eine Methodik bei der Entwicklung von (Unit-) Tests. Dieser Artikel diskutiert die Vor- und Nachteile der testgetriebenen Entwicklung und wann TDD zum Irrweg wird.
TDD ist eine aus XP (eXtreme Programming) bekannte Methodik, bei der die Unittests vor der eigentlichen Implementierung kodiert werden. Basierend auf den Anforderungen an das Programm werden in kurzen Iterationen Tests und erst nach einem Test die entsprechende Lösung entwickelt. Da es bei bzw. direkt nach der Entwicklung des Tests noch keine Implementierung gibt, gegen die der Test ausgeführt werden kann, schlägt jeder Test zunächst fehl. Man sagt auch, der Test ist rot. Im nächsten Schritt wird die Implementierung für den Test geschrieben. Der Test wird dadurch grün. Danach kann die Implementierung refaktoriert werden (blau). Der TDD Zyklus ist also:
Oder auch:
Vorteile
Die testgetriebene Entwicklung kann Vorteile bringen. Dazu werfen wir einen Blick auf die einzelnen Schritte im TDD Zyklus:
Write Test Code
Das Schreiben von Testcode vor der eigentlichen Implementierung mag zunächst komisch anmuten. Es bringt jedoch den Vorteil, dass die Testabdeckung des Produktivcodes erhöht ist. Produktivcode wird nur aus dem Zweck heraus geschrieben den Testcode zu "erfüllen".
Write Functional Code
Die vorab geschriebenen Tests definieren die Anforderungen an unser Programm. Tests werden also direkt aus den Anforderungen abgeleitet. Dadurch, dass es bereits einen Test gibt, und unsere Implementierung gegen den Test geschrieben wird, stellt TDD sicher, dass die Anforderungen erfüllt sind. Der Test ist zudem eine Dokumentation für den danach geschriebenen Code. Allerdings gilt dieser Punkt auch für Unittests die nicht mittels "Test first" geschrieben wurden.
Refactor
Der letzte Schritt im TDD Zyklus ist der Refactoring Schritt. Das Design des vorab geschriebene Programmcodes wird verbessert. Sie stellen sicher, dass der Code den Zweck zum Ausdruck bringt und verständlich ist. Dass der Programmcode weiterhin korrekt ist, kann durch erneutes Ausführen der Tests einfach validiert werden. An dieser mikroskopischen Stelle ist Refactoring übrigens auch ein zulässiger Schritt. Kritischer ist Refactoring zu betrachten, wenn es zu einem späteren Zeitpunkt durchgeführt wird, oder mehrere Codestellen betrifft (siehe "Vorsicht wenn Entwickler den Begriff Refactoring verwenden").
Nachteile und Lösung
TDD ist nicht prinzipiell schlecht. Allerdings proklamieren viele Befürworter von TDD, dass die Entwicklung in Baby-Steps und das Schreiben des Testscodes vor dem Produktivcode, zu einem "speziellen Softwaredesign" führt (was auch immer das genau bedeuten mag). Klar ist: dadurch, dass der Test vor der Implementierung geschrieben wird, ist ein Entwickler dazu gezwungen seinen zukünftigen "Produktivcode" selbst zu verwenden, noch bevor es ein dritter (Kollege o.ä.) muss. Dadurch werden zumindest Usability-Probleme im Interfacedesign früh erkannt.
Durch den starken Fokus auf den zu entwickelnden Test bzw. dessen Lösung, geht jedoch auch der Blick aufs Große und Ganze verloren. Mit zunehmender Entwicklungszeit entstehen immer mehr Abhängigkeiten zwischen den einzelnen (getesteten) Units. Die Units "verweben" sich miteinander. Es entsteht Spaghetticode. Deswegen sollten Sie auch bei TDD auf die wichtige Konzeptphase (auch Definitionsphase genannt) keinesfalls verzichten. Entwerfen Sie das Softwaredesign auf höherer Flugebene gemeinsam im Team - und setzen Sie die Lösung dann auf niedrigerer Flugebene um, gerne mit TDD.