Projektmanagement Softwareentwicklung

Softwareentwicklung für Projektleiter, Manager und Entwickler

IT-Projektmanagement RSS
  • TDD (Test Driven Development): Wo liegt denn nun tatsächlich der Vorteil?

    Jörg Hinrichs

    Neulich bin ich über einen interessanten Blogartikel gestolpert, wo es um Test Driven Development (TDD) ging: TDD in der (meiner) Praxis – Wunsch und Wirklichkeit. Test Driven Development bedeutet im Wesentlichen, dass ein automatisierter Test bereits geschrieben wird, bevor die Implementierung des zugehörigen Anwendungscodes stattfindet.

    Kann ich mir TDD leisten?

    Da ging es vor allem um die Frage: Kann ich mir TDD eigentlich leisten? Wie hoch ist der Mehraufwand? Und wenn ich das in mein Angebot einpreise, kriege ich dann überhaupt noch einen Auftrag?

    Oder andersherum gefragt: Wieviel TDD kann ich mir leisten? Welche Funktionalitäten sind es wert getestet zu werden und wo kann ich gegebenenfalls auf Tests verzichten, um konkurrenzfähig zu bleiben?

    Der Artikel ist auf jeden Fall lesenswert und das gilt auch für die nachfolgende sehr ausführliche Diskussion in Form von Kommentaren. Ich möchte hier einige eigene Gedanken dazu beisteuern, aber lassen Sie mich vorher noch einmal einen Schritt zurückgehen.

    Was soll TDD denn eigentlich leisten?

    Argumente für TDD gibt es viele. Hier eine kleine Auswahl der wichtigsten:

    1. weniger Bugs / bessere Qualität bei Auslieferung
    2. weniger Kosten, da Fehler früher gefunden werden
    3. weniger Angst vor Refactoring / Änderungen allgemein
    4. persönliche Befriedigung des Entwicklers
    5. besseres Design
    6. höhere Produktivität

     Wenn ich mir diese Liste so anschaue stelle ich fest, dass die ersten 4 Punkte eher Argumente für automatisierte Tests im Allgemeinen aber nicht unbedingt für TDD im Speziellen sind.

    Weniger Bugs bei Auslieferung (und damit gleichzeitig auch weniger Kosten und bessere Qualität) erhalte ich in jedem Fall. Da ist es relativ egal, ob ich die Tests vor oder nach der Implementierung schreibe.

    Dasselbe gilt für die Angst vor dem Refactoring von kritischen Programmbestandteilen und die persönliche Befriedigung des Entwicklers über das Schreiben von funktionierendem Code. Sicher wird es leichte Unterschiede geben aber ich halte die für vernachlässigbar.

    Eine Voraussetzung gibt es allerdings: Die neu entwickelten Funktionalitäten dürfen nicht zu umfangreich sein. Und außerdem muss es Tests für den bestehenden Code geben. Wenn ich also ein halbes Jahr entwickle und dann anschließend die Tests für meinen Code schreibe, dann wird das einen deutlichen Unterschied beim Aufwand im Vergleich zu TDD machen.

    Solange wir aber über kleine Einheiten von wenigen Wochen reden (typisch beispielsweise für Sprints in der agilen Softwareentwicklung oder die Entwicklung einzelner Features), ist der Unterschied sicher vernachlässigbar. Wichtig dabei ist, dass der Testcode zu dieser Einheit dazugehört.

    Und was ist mit dem Design?

    Test Driven Development führt zu besserem Design – kriegt man jedenfalls oft zu hören. Ich glaube da muss man etwas differenzieren.

    Auf der Komponentenebene, wo ich einzelne Methoden einer Klasse teste, macht es meiner Meinung nach keinen Unterschied. Warum?

    Woran erkennt man gutes Design? Es lässt sich leicht erweitern, ist leicht zu verstehen, vermeidet viele Abhängigkeiten und nicht zuletzt bildet es die Realität möglichst naturgetreu ab.

    Und wie kommt man zu einem solchen Design? Durch viel Wissen und noch mehr Erfahrung. Aber sicher nicht durch Unit Tests. Wenn Sie nicht wissen, wie man ein gutes Design entwirft und wodurch es sich auszeichnet, dann werden Unit Tests sie nicht “automagisch” dort hinführen.

    Etwas anders sieht das aus bei Tests, die dem normalen Arbeitsablauf der Benutzung einer Software nachempfunden sind. Das sind dann keine klassischen Unit Tests mehr aber natürlich kann man die auch automatisieren (siehe Unit Tests: Zeitverschwendung?).

    So ein Arbeitsablauf ist besonders wichtig in der Anforderungsklärung und das hat natürlich auch Auswirkungen auf das Design der Anwendung. Für mich wird aber eigentlich andersherum ein Schuh daraus: Erst ermittle ich die Arbeitsabläufe, dann generiere ich daraus die zugehörigen Testfälle.

    Das führt dann auch zu einem besseren Design, aber nicht aufgrund von TDD. Es sei denn, ich habe mir vorher keine Gedanken über die Arbeitsabläufe gemacht, dann wird das bei der Definition der Testfälle sozusagen implizit nachgeholt.

    Insofern kann ich sagen, dass  TDD hier tatsächlich zu einem besseren Design führt. Wenn ich allerdings vorher meine Hausaufgaben gemacht habe, dann brauche ich dafür TDD nicht mehr – jedenfalls nicht für das Design.

    Manche Entwickler sind ja der Meinung, dass Testfälle allein als Ersatz für eine Spezifikation dienen können. Ich habe mich für diesen Gedanken nie so recht erwärmen können. Was denken Sie darüber?

    Produktivität

    Damit bin ich beim letzten Punkt angelangt: Ist ein Entwickler mit TDD produktiver als ohne? Die Frage finde ich gar nicht so leicht zu beantworten. Ich denke, dass hier mehrere verschiedene Aspekte eine Rolle spielen.

    1. Die Art der Anwendung
      Bei interaktiven Anwendungen wie beispielsweise Verwaltungssoftware auf Basis von Datenbanken, wo es hauptsächlich um die Anzeige und Pflege ausgewählter Informationen geht, ist der manuelle Testaufwand traditionell sehr groß.
      Hier erscheint mir TDD sehr attraktiv, da es den Zeitaufwand des Testens stark reduziert. Bei Batchanwendungen dagegen gewinnt man durch Automatisierung nicht viel. Die sind ja im Grunde von Haus aus schon automatisiert.
    2. Entwicklungsgewohnheiten
      Wenn ich selber entwickle, schreibe ich normalerweise 10-20 Zeilen Code und teste diese dann. Ganz selten sind es einmal 50 Zeilen oder mehr.
      Das bedeutet, dass Tests einen beträchtlichen Teil meiner Entwicklungszeit ausmachen. Ich habe es nie wirklich gemessen, aber es würde mich nicht wundern wenn der Anteil bei 20 – 40 Prozent liegt. In so einem Fall können automatisierte Tests tatsächlich eine Menge Zeit sparen – mehr als es kostet sie zu schreiben.
    3. Testaufwand
      Die meisten Tests kann man sehr schnell erstellen. Im Gegensatz zur Entwicklung der eigentlichen Anwendung muss hier nicht so viel Planungsaufwand betrieben werden.
      Tests können aber auch recht aufwändig werden, z.B. wenn Sie komplette Arbeitsabläufe bei einer Datenbankanwendung testen wollen. Wenn das wirklich sauber funktionieren soll, dann müssen die dazugehörigen Daten komplett für die Tests bereitgestellt werden – und anschließend wieder entsorgt werden, damit der nächste Testdurchlauf auch noch funktioniert.

    Grundsätzlich habe ich die Erfahrung gemacht, dass TDD sich lohnt – auf jeden Fall bei den Anwendungen, mit denen ich hauptsächlich zu tun hatte. Unter anderen Rahmenbedingungen kann es aber auch vorkommen, dass Sie keinen Nutzen daraus ziehen.
    Wohlgemerkt: Ich beziehe das nur auf TDD im Speziellen, nicht auf automatisierte Tests im Allgemeinen.

    TDD und Termine

    Es gibt noch einen weiteren wichtigen Aspekt im Zusammenhang mit TDD: Es sorgt dafür, dass automatisierte Tests auch tatsächlich geschrieben werden!
    Das hört sich auf den ersten Blick ein wenig seltsam an. Falls Wenn ihr Projekt jedoch unter Termindruck gerät, dann gehören Tests zu den Dingen, die als erstes unter den Tisch fallen (das gilt übrigens nicht nur für automatisierte Tests).

    Mit TDD kann das nicht passieren, denn die Tests werden noch vor dem eigentlichen Code geschrieben. Das führt dazu, dass die Qualität der Software bestehen bleibt und dann eher der Terminplan oder der Funktionsumfang angepasst werden – es sei denn die Tests werden komplett gestrichen.

    Dieser Punkt allein wäre für mich schon ausreichend, um TDD einzuführen – natürlich nur, sofern die übrigen Rahmenbedingungen für automatisierte Tests sprechen.

    Published on Dezember 21, 2011 · Filed under: Entwickler, Software-Architekt, Test, Unit-Test Test-Driven-Development; Tagged as: ,
    4 Comments

4 Responses to “TDD (Test Driven Development): Wo liegt denn nun tatsächlich der Vorteil?”

  1. Hallo Jörg,

    danke für den schönen Artikel, ich finde gerade den Punkt gut erfasst, dass TDD kein Design ersetzt und man dennoch Erfahrung dafür braucht.

    Ich finde es wichtig, dass man sich vorher Gedanken um die Platzierung seiner Klasse macht, ein Unit-Test ist schließlich nur ein kleiner Ausschnitt.
    Die Aufgabe einer Klasse oder Methode muss mich aber in Richtung meines gesamten Designs voran bringen, was auf dieser Ebene alleine schwer zu beurteilen ist.

    Des weiteren verfolge ich gerne einen Bottom-Up Ansatz um möglichst generische Teilmodule zu bekommen, dabei will ich mich aber auch nicht in Verallgemeinerung verlieren, was bei diesem Ansatz leicht passieren kann.

    Hier finde ich es hilfreich bereits einen Fahrplan, in Form einer groben Spezifikation zu haben, die auch als Diskussionsgrundlage dienen kann und z.B. als Grafik vorliegt. Dies erscheint vielen Kollegen auch als angenehmer.
    Zudem möchte ich behaupten es ist trotz sehr guter Tool Unterstützung oftmals doch schneller ein paar Linien und Kästchen zu verschieben als dies direkt mit Klassen zu veranstalten.
    Daraus folgt für mich, dass Unit-Tests alleine keine Spezifikation ersetzen, die Funktion einer einzelnen Unit jedoch gut beschreiben können.

    Bei Integrations- und Akzeptanztests könnte man jedoch in der Tat noch ein wenig mehr darüber streiten ob sie als maßgeblich anzusehen sind. Hier würde ich auch gerne noch mehr Erfahrungen sammeln, es geht dann allerdings eher in Richtung BDD.

    Viele Grüße

    Benjamin Peter

  2. Jörg Hinrichs said on

    Hallo Benjamin,

    ich gebe Dir Recht, ein Unit-Test ist einfach zu unstrukturiert, um eine Spezifikation zu ersetzen. Es besteht immer die Gefahr, wesentliche Bestandteile der Funktionalität zu übersehen, weil bestimmte Fragen erst gar nicht gestellt werden. Das betrifft zum Beispiel die systematische Suche nach den Interessenten an einem Feature und deren Zielen.

  3. Hey, dein Post auf deinem Blog ist ehrlich erfrischend. Normalerweise lese ich nicht bis zum Schluss, aber das war ganz ehrlich mal ein fesselnder Post. Erfrischend! Bin allerdings nur durch Zufall über Altavista auf deine Webseite aufmerksam geworden. Zum eigentlichen Thema: gibt es hierzu mittlerweile etwas Neues? Habe auf deiner Webseite gesucht, aber leider nichts gefunden. Vielen Dank und so weitermachen!

  4. Ich denke, TDD ist eine vollständig andere Herangehensweise Code zu schreiben. In der Regel will man doch, dass eine Methode funktioniert und probiert das aus. TDD lässt den Entwickler noch einmal nachdenken, was seine Methode denn alles verdauen muss, wenn die übergebenen Argumente nicht die richtigen sind. Heraus kommt mit TDD auf jeden Fall etwas robusteres als ohne.

Leave a Reply