Als testgetriebene Entwicklung (auch testgesteuerte Programmierung, engl. test first development oder test-driven development (TDD), manchmal auch scherzhaft Extreme Testing) bezeichnet man die Verwendung Agiler Methoden zur Entwicklung eines Computerprogramms, bei der die Programmierer Software-Tests konsequent vor den zu testenden Komponenten entwickeln. Die dazu erstellten Unit-Tests sind Grey-Box-Tests statt klassischer White-Box-Tests. Die wohl bekannteste Agile Methode ist das Extreme Programming.
Inhaltsverzeichnis |
Nach klassischer Vorgehensweise, beispielsweise nach dem Wasserfall- oder dem V-Modell, werden Tests parallel zum und unabhängig vom testenden System entwickelt oder sogar nach ihm. Dies führt oft dazu, dass nicht die gewünschte und erforderliche Testabdeckung erzielt wird. Mögliche Gründe dafür sind unter anderem:
Ein weiterer Nachteil klassischer White-Box-Tests ist, dass der Entwickler das zu testende System und seine Eigenheiten selbst kennt und dadurch aus Betriebsblindheit unversehens "um Fehler herum" testet.
Die Methode der testgetriebenen Entwicklung versucht, den Gründen für eine nicht ausreichende Testabdeckung und einigen Nachteilen der White-Box-Tests entgegenzuwirken.
Bei der testgetriebene Entwicklung ist zu unterscheiden zwischen dem Testen im Kleinen (Unit-Tests) einerseits und dem Testen im Großen (Systemtests, Akzeptanztests). Wobei Beck's Methode auf Unit-Tests ausgelegt ist.
Unit-Tests und mit ihnen getestete Units werden stets parallel entwickelt. Die eigentliche Programmierung erfolgt in kleinen und wiederholten Mikroiterationen. Eine solche Iteration, die nur wenige Minuten dauern sollte, hat drei Hauptteile:
Diese drei Schritte werden so lange wiederholt, bis die inzwischen geschaffenen Tests alle bestanden werden und dem Entwickler keine sinnvollen weiteren mehr einfallen, die vielleicht noch scheitern könnten. Die so behandelte programmtechnische Einheit (Unit) wird dann als (vorerst) fertig angesehen.
Die konsequente Befolgung dieser Vorgehensweise läuft auf evolutionärem Entwurf hinaus, weil die ständige Änderung Weiterentwicklung eines Systems in den Vordergrund rückt.
Da der einzelne Unit-Test sowohl Züge eines White-Box-Tests als auch eines Black-Box-Tests aufweist, bezeichnet man ihn auch als Grey-Box-Test.
Systemtests werden immer vor dem System selbst entwickelt oder doch wenigstens spezifiziert. Aufgabe der Systementwicklung ist bei testgetriebener Entwicklung nicht mehr, wie klassisch, schriftlich formulierte Anforderungen zu erfüllen, sondern spezifizierte Systemtests zu bestehen.
Bei beiden Arten von Tests wird eine möglichst vollständige Testautomatisierung angestrebt. Für testgetriebene Entwicklung müssen alle Tests einfach („per Knopfdruck“) und möglichst schnell ausgeführt werden können. Für Einheitstests bedeutet das eine Dauer von wenigen Sekunden, für Systemtests von maximal einigen Minuten, bzw nur in Ausnahmen länger.
Die großen Vorzüge der testgetriebenen Methodik gegenüber der klassischen sind:
Testgetriebene Entwicklung ist wesentlicher Bestandteil des Extreme Programming (XP) und anderer agiler Methoden. Auch außerhalb dieser ist sie anzutreffen, häufig in Verbindung mit der Paarprogrammierung .
Die testgetriebene Entwicklung braucht vordinglich
damit die Iterationen schnell und unkompliziert durchlaufen werden können.
Bei der Java-Entwicklung kommen dafür meist Ant und JUnit zum Einsatz. Für die meisten anderen Programmiersprachen existieren ähnliche Werkzeuge, wie z. B. für PHP die PEAR-Erweiterung PHPUnit.
Für komplexe Systeme müssen mehrere Teilkomponenten unabhängig voneinander entwickelt werden und es finden dazu auch noch Fremdkomponenten Verwendung, etwa ein Datenbanksystem zwecks persistenter Datenhaltung. Die korrekte Zusammenarbeit und Funktion der Komponenten im System muß dann auch getestet werden. Um nun die Einzelkomponenten dabei separat testen zu können, die doch aber zu ihrer korrekten Funktion wesentlich von anderen Komponenten abhängen, verwendet man Mock-Objekte als deren Stellvertreter. Die Mock-Objekte ersetzen und simulieren im Test die benötigten anderen Komponenten in einer Weise, die der Tester ihnen einprogrammiert.
Ein Werkzeug für Akzeptanztests und Systemtests ist beispielsweise Framework for Integrated Test. Eine beliebte FIT-Variante ist Fitnesse, ein Wiki-Server mit integrierter Testerstellung- und Testausführungsumgebung.
Auch die Methode der testgetriebenen Entwicklung kann falsch eingesetzt werden und dann scheitern. Programmierern, die noch keine Erfahrung dabei besitzen, erscheint sie manchmal schwierig oder gar unmöglich. Sie fragen sich, wie man etwas testen soll, das doch noch gar nicht vorhanden ist. Auswirkung kann sein, dass sie die Prinzipien dieser Methode vernachlässigen, was insbesondere bei agilen Methoden wie dem Extreme Programming Schwierigkeiten beim Entwicklungsprozesse oder sogar dessen Zusammenbruch zur Folge haben kann. Ohne ausreichende Einheitstests wird keine ausreichende Testabdeckung für Refaktorisierungen und die gewünschte Qualität erreicht. Dem kann man mit Paarprogrammierung und Schulung entgegenwirken.
Auch diese stark auf Tests setzende Art der Programmierung kann nicht jeden Fehler aufdecken. Insbesondere nicht Fehler, die programmextern entstehen: Timingfehler wie Thread-Deadlocks, Fehler bei der RS232-Kommunikation usw. Ebenfalls kann es an der nötigen Testabdeckung mangeln, wenn nicht alle potentiellen Eingaben einer Funktion getestet werden können. Dies ist etwa der Fall, wenn etwa die Eingabe aus sehr vielen Einzeldaten besteht; dann kann aufwandshalber nicht mehr jede mögliche Kombination von Eingabedaten getestet werden. Fehler bei Benutzungsoberfächen sind schlecht testbar, weil natürlich kein automatisierter, prüfender „Testblick“ auf die Folge der Bildschirmdarstellungen und die Verständlichkeit von Darstellung und Textelementen möglich ist. Um anderswie noch Fehler zu finden, sind Integrationstests und Systemtests erforderlich.