Unit Tests, TDD und Testbarkeit: Ja!
Vor ein paar Tagen stellte Golo die Frage “Wieviel Sinn machen Unit Tests?” in seinem Blog. Dieser Frage stellten sich schon Peter sowie Thomas in ihren Blogs. Ich habe die Fragestellung schon vor einiger Zeit mit dem Artikel “Wozu Unit Tests?” aufgegriffen und beantwortet, möchte aus aktuellem Anlass meine bescheidene Meinung noch ein wenig mehr ausformulieren.
Unit Tests & TDD machen Sinn!
Ganz ehrlich, Unit Tests & TDD machen sogar richtig viel Sinn. Unit Testing selbst macht schon sehr viel Sinn, weil eine Verifikation von Anforderungen (fachlicher und technischer Natur) ein wichtiger Bestandteil in der Beurteilung von Leistungsanforderungen an eine Software sind. Ha! Komischer Satz irgendwie, aber im Endeffekt einfach abkürzbar: Wer will ein Auto ohne getestete Bremsen fahren? Übrigens auch ein ziemlich netter Vergleich, denn “bremsen” ist das Feature, welches von verschiedensten Komponenten und Faktoren abgedeckt wird (Bremsflüssigkeit, ABS, Bremsscheiben, Bremsbacken, Bremsblöcke usw usf.). Naja, ich glaube da gibt es nicht viel mehr darüber zu sagen.
Darüber hinaus geht es beim Testing & Test-Driven-Development um die Entwicklung von stabiler Software. Stabil ist in diesem Sinne nicht nur die Verifikation der Funktionalität (”Im Werk wurde einmal auf die Bremse getreten, der Wagen blieb stehen – Passt.”), sondern um die Haltbarkeit der Funktionalität als Subsystem (die gesamte Bremsanlage) und innerhalb des Gesamtsystems (Auto). Kurz und bündig: Wer heutzutage stabile, wartbare und erweiterbare Software entwickeln möchte wird ernsthaft TDD einsetzen wollen.
TDD ist ein mächtiges Entwicklungswerkzeug
Wie Ralf es schon in seinem Post über TDD erklärt und in vielen Kommentaren wiederholt, darf man TDD nicht als das “Allheilmittel” ansehen, sondern als dediziertes, mächtiges Werkzeug. Mit TDD als Tool kann man viele Dinge sicherer und schneller gestalten. Mittlerweile kann ich behaupten, dass ich TDD in keinem Projekt außer acht lassen will und werde, weil es ein essentielles Werkzeug in meinem “Software-Entwicklungs-Baukasten” ist – wie z.B. eine gute IDE oder Patterns oder SCM oder CI… TDD ist einfach mit dabei.
Manch einer macht hierbei noch eine feine Unterscheidung. Es heisst: “Bei neuen Projekten TDD, ok. Aber bei den alten Dingern? Boa, nee”. Ehrlich gesagt habe ich das am Anfang auch so gesehen. Aber Mittlerweile sehe ich das ganz anders. Egal ob Green- oder Brownfield – TDD ist immer gut. Bei schon existierenden Projekten (die evtl. sogar wenig Tests haben) treibt TDD die Testbarkeit und die lose Kopplung voran, fördert die Effektivität der Arbeit an Erweiterungen und erleichtert vehement die Umstrukturierung und Wartung des Codes. Dort wo es machbar ist, sollte TDD auch gemacht werden, denke ich.
Jaaa, aber wo ist denn TDD nicht machbar? Klare Antwort: I/O und Parallelität / Multithreading. Alles was mit Ein- und Ausgabegeräten zu tun hat, eine Ressource für Ein- oder Ausgabe darstellt oder in einem asynchronen Verarbeitungskontext liegt. In der Praxis: Joystick, Komplexe Eingaben, User Interfaces, Datenbank. Das sind kritische Punkte, ja. Und gerade dort wünscht man sich TDD, obwohl genau dort die Grenzen früher oder später erreicht werden, weil man einfach keinen Einfluss mehr auf den Status, die Eingabe, die Ausgabe oder die Erwartung derer hat.
TDD im Grenzbereich
Dennoch darf man sich nicht durch diese “Schwierigkeiten” abschrecken lassen. Ich habe gerade bei diesen Situationen festgestellt, dass es enorm hilfreich sein kann, am “Grenzbereich” von TDD sprichwörtlich “bis zum geht nicht mehr” umzusetzen. Man stellt schnell fest, dass man an diesen “Nahtstellen” der Anwendung sauberer und klarer strukturiert, Verantwortlichkeiten besser aufteilt. Danach betrachtet man das Ergebnis mit anderen Augen. Man stellt fest, dass die UI wirklich nur noch das nötigste macht, absolut schlank ist und dass viele Dinge, die in der UI hilfreich sind (wie z.B. “Pagination”) auch komplett ohne UI wunderbar anwendbar werden. Da ist TDD ein wenig wie beim Autorennen: Im Grenzbereich ist es anstrengend, ist aber hocheffektiv und macht obendrein noch Spass.
Für die TDD-Stirnrunzler, die wirklich mal wissen wollen, wie sich das dann im Endeffekt anfühlen kann, denen lege ich wärmstens ein paar Code Kata’s an’s Herz. Zum Beispiel ist das populäre KataFizzBuzz im letzten Einsteiger-Dojo als Windows-Forms-Kata implementiert worden. Dort gab es viele, die sich gefragt haben, wie man überhaupt die UI testen kann. Doch statt sich mit der “Untestbarkeit” der GUI zufrieden zu geben, hat man konsequent das TDD ausgereizt und dadurch ein einfaches MVP-Pattern umgesetzt.
Für TDD-Neulinge empfehle ich auch das KataBlog. Es ist eine wunderbar einfache Programmieraufgabe, die sehr subtil zeigt, wie man über TDD Design & Entkopplung der Verantwortlichkeiten treibt und welche (anfangs ungeahnten) Vorteile man sich dadurch schaffen kann. Jedoch warne ich die Interessierten schon vor: KataBlog zeigt die Erkenntnisse subtil, zwischen den Zeilen.
Fazit: TDD & Unit Testing ist ein absolutes Muss in der modernen Software-Entwicklung!








Ich bin vollkommen deiner Meinung. Um eine qualitativ hochwertige Software zu bauen, die alle Anforderungen wie gewünscht umsetzt, ist Software testen ein wesentlicher Bestandteil. Gerade die Entwicklertests, also Unittests, tragen einen entscheiden Anteil effizienten Code zu schreiben. Dabei kann man je nach Geschmack zwischen dem Tear Down oder Bottom Up Ansatz vorgehen (Schreibe ich erst die Funktion oder erst den Testfall für die zu implementierende Funktion). Allerdings finde ich dass TDD nur der erste Schritt ist um gute Software zu schreiben. Es sollte immer in allen Phasen der SW-Entwicklung getestet werden. Auch wenn das manchmal nervt. Eine gut getestete Software weist nicht nur Qualität nach, sondern verhindert später aufwendiges Nachpatchen, bzw. vereinfacht die spätere Wartung der Anwendung. Aber neben Tests sollte man sich auch vor der Codierung Gedanken um das Design(Wie sieht die Architektur der Software aus, welche Klassen werden benötigt etc.) einer Anwendung machen. Auch wenn man als Entwickler dazu neigt direkt mit dem entwickeln anfangen zu wollen.
Ihre Meinung ist gefragt!