Die Effektivität von Test Driven Development

Von am 15.02.2021

Photo by Clément Hélardot on Unsplash

Agiles Arbeiten ebnet den Weg für testgetriebene Entwicklung

Im Agilen Manifest, welches im Jahre 2001 von den Begründern der agilen Software Entwicklung formuliert wurde (Beck et al., 2001), nannte man testgetriebene Entwicklung neben  Kundenakzeptanztests als eine der beiden wichtigsten Testpraktiken. Auch beim Extreme Programming ist testgetriebene Entwicklung eine zentrale Instanz (Khanam & Ahsan, 2017). Somit rückten die Vertreter agiler Methoden in den letzten Jahrzehnten auch das Test Driven Development (TDD) ins Rampenlicht.

Testgetriebene Entwicklung sieht den bisher sehr verbreiteten Code then test-Ansatz als veraltet an, bei dem das Programm zunächst entwickelt wird und im Nachhinein die Tests dazu erstellt werden. Viel effektiver sei es, die Testfälle jeweils für einen kleinen Teil des Programms im Vorhinein zu entwickeln. Der darauffolgend geschriebene Programmcode wird so lange bearbeitet, bis die Tests erfolgreich abschließen. Nach jeder kleinen Erweiterung des Programms (Increment) wird der Code refactored, um die Tests nicht nur mit einem grünen Häkchen zu versehen, sondern auch gute Code-Qualität zu erreichen (Shull et al., 2010).

Khanam und Ahsan (2017) merken an, dass es wichtig sei, zwischen Unit Testing und der Gesamtheit des Test Driven Developments zu unterscheiden. Unit Testing garantiert das Verhalten von Code, während TDD darüber hinaus maßgeblich die Entwicklung der Software beeinflusst.

David Astels beschreibt in seinem Buch Test Driven Development: A Practical Guide (2003) testgetriebene Entwicklung als eine Software-spezifische Entwicklungsmethode,

  • wo eine große Anzahl an Software Tests durchführt wird,
  • wo kein Code ohne zugehörige Tests in das Produktiv-System gelassen wird,
  • wo die Tests vor dem Code geschrieben werden und
  • wo die Tests bestimmen, welcher Code geschrieben werden muss.

Dieser Test-First-Ansatz sei laut Erdogmus et. al (2005) das zentrale Element von testgetriebener Entwicklung. Außerdem sei wichtig, dass die Tests von derselben Person bzw. von demselben Team entwickelt würden, die auch den Code zur Lösung des Tests schreiben. Damit setzt es sich klar von der Cleanroom-Technik ab, wo zwar auch Tests vor der Entwicklung der Software erstellt werden, die Tests jedoch von einem eigenen Team mithilfe von zukünftigen Nutzerinnen und Nutzern durchgeführt werden und statistischer Natur sind. Meist sind die Tests bei Test Driven Development eher mit geringem Aufwand erstellt und decken lediglich die Funktionalität der zu erfüllenden User Stories ab.

Abbildung 1: Test-Last (links) im Vergleich zu Test-First (rechts) (Erdogmus et al., 2005).

Dieser Artikel fasst die Ergebnisse einiger wissenschaftlicher Arbeiten zum Thema testgetriebene Software-Entwicklung zusammen und präsentiert die Stärken und Schwächen. Den Abschluss bildet ein Fazit und eine Bewertung der Effektivität von Test Driven Development.

Auswirkungen auf die Qualität des Produkts

Forrest Shull und seine Kolleginnen und Kollegen haben in ihrem Artikel, erschienen in der IEEE Software (2010), bereits zahlreiche Studien zur testgetriebenen Entwicklung erfasst und deren Ergebnisse ausgewertet.  In Anbetracht von acht Pilotstudien, sechs überwachten Experimenten und sieben Branchenstudien kommen sie zu dem Schluss, dass die Ergebnisse von über 60 % der Studien (13 Werke) auf eine Verbesserung durch Test Driven Development (TDD) hindeuten. Sechs Arbeiten stellen keinen Unterschied zwischen den bisherigen Programmierpraktiken und TDD fest. Nur zwei Arbeiten behaupten, eine Verschlechterung zu erkennen.

Aber was macht testgetriebene Entwicklung so erfolgreich? Zunächst liefert es direktes Feedback. Tests, die vor der Entwicklung eines Features geschrieben wurden, bieten der Programmiererin / dem Programmierer sofortige Rückmeldung, ob die Funktionalität des Features erreicht wurde und ob sich die neue Funktionalität auf bisherige negativ auswirkt, sprich ob bereits implementierte Funktionalität bei der Implementierung der neuen Funktionalität beschädigt wurde (Erdogmus et al., 2005; Khanam & Ahsan, 2017).

Durch Test Driven Development wird das Schreiben von Tests ein zentraler Teil der Entwicklung. Es wird nicht erst im Nachhinein eingeplant oder gar darauf verzichtet. Es treten weniger Fehler auf und das Projekt wird somit effizienter (Maximilien & Williams, 2003).

TDD lässt das Entwicklerteam den Code in lösbare, ausführlich formulierte Aufgaben herunterbrechen, was den Fokus auf die Funktionalität erhält und den Fortschritt besser messbar macht (Erdogmus et al., 2005; Khanam & Ahsan, 2017). Außerdem bringt es die Entwicklerinnen und Entwickler dazu, von Beginn an von einer Endnutzer-Perspektive aus zu denken (Khanam & Ahsan, 2017).

Testgetriebene Entwicklung trägt zur Qualitätssicherung bei. Wenn man zahlreiche Tests auf dem neuesten Stand parat hat und diese regelmäßig ausführt, garantiert dies ein gewisses Grundlevel an Qualität des geschriebenen Programmcodes (Erdogmus et al., 2005). Die Tests können als Dokumentation dienen (Khanam & Ahsan, 2017). Durch die regelmäßige Testung des Increments werden Spätfolgen bei einer Zusammenführung der Features am Schluss vermieden (Maximilien & Williams, 2003).

Es unterstützt außerdem das architekturelle Design der Software, indem anhand der Funktion, die getestet werden soll, Entscheidungen über den Aufbau der Klassen und Methoden, deren Nomenklatur und deren Schnittstellen mit Fokus auf die Funktionalität getroffen werden können (Erdogmus et al., 2005; Khanam & Ahsan, 2017; Maximilien & Williams, 2003).

Refactoring ist ein wichtiger Aspekt, der durch testgetriebene Entwicklung erleichtert wird. Es beschreibt das Verändern von bereits existierendem, funktionierendem Code, ohne die Funktionalität zu verändern. Das Ziel ist es, die interne Struktur des Codes zu verbessern. Dieser Refactoring-Prozess dient dazu, nach der Erfüllung der Akzeptanzkriterien, sprich der Erfüllung der Tests, die Qualität des Codes zu erhöhen. Mithilfe von Test Driven Development kann das Refactoring ohne Angst vor Verlust des Funktionsumfangs durchgeführt werden, da die Tests die Funktionalität des Codes absichern (Astels, 2003; Khanam & Ahsan, 2017).

Kent Beck schreibt in seinem Werk Test Driven Development By Example (2003), dass dieser Effekt des Testens und des Refactorings sogar so wichtig sei, dass es sich lohne, dafür Aufwand zu betreiben. Für bessere Testmöglichkeiten zahle es sich aus, die Code Struktur zu verändern und somit testbar zu halten, wenn das mit der bisherigen Struktur nicht gewährleistet wäre (z.B. zu große Test-Fälle).

Für David Astels (2003) sei es vor allem wichtig, dass TDD, gemeinsam mit dem Einsatz agiler Methoden einen denken-bevor-man-handelt-Ansatz forciert. Außerdem führe der Gedanke, wie man gewisse Anforderungen testen kann, zu mehr Testfällen, die das Programm ausfallssicherer machen.

Auswirkungen auf die Produktivität

Es ist anhand dieser zahlreichen Vorteile einfach sich vorzustellen, dass testgetriebene Entwicklung die Produktqualität verbessert. Dass es jedoch auch die Produktivität des Entwicklungsteams erhöht, widerspricht den Stimmen vieler erfahrener Software Experten alter Schule. Entgegen deren Annahme, dass Tests einen Overhead die Zeit und das Budget betreffend erzeugen und deswegen von einem eigenen Qualitätssicherungsteam durchgeführt werden sollen, biete TDD laut Erdogmus et al. (2005) auch klare Vorteile für die Produktivität des Teams, wenn es direkt von den Entwicklerinnen und Entwicklern durchgeführt wird.

So ergibt die Auswertung des Experiments in der Arbeit von Erdogmus et. al (2005) einen linearen Zusammenhang zwischen der Anzahl der Tests und der Produktivität des Teams. Dies sei auf ein besseres Verständnis der Aufgabenstellung, einen besseren Fokus auf die Funktionalität, schnelleres Lernen aus und Ersetzen von falsch gewählten durch effektivere Strategien und weniger Aufwand beim Ausbessern von Fehlern zurückzuführen. Diesen geringeren Aufwand belegt auch das Experiment von Maximilien and Williams (2003), bei dem durch Anwendung von TDD 50% weniger Fehler im Programm aufgetreten sind. Der Einsatz von TDD mag den Entstehungsprozess zunächst verlangsamen, unterstützt das Team aber und treibt die Produktivität auf lange Sicht gesehen an (Khanam & Ahsan, 2017).

In der Arbeit von Erdogmus et al. (2005) kommen die drei Autoren sogar zu dem Schluss, dass die Auswirkung von Test Driven Development (im Vergleich zu normalem Software Testing nicht im Vergleich zur Entwicklung ohne Testung!) auf die Qualität schwieriger nachgewiesen werden kann und bestätigen nur die Auswirkung auf die Produktivität des Teams. Warum die Andeutung auf eine Verbesserung der Qualität des Produkts so undeutlich ausgefallen ist, erklären die Autorinnen und Autoren unter anderem dadurch, dass der Umfang des beobachteten Programmes zu klein gewesen sei und in dieser Größenordnung auch die Erfahrung und Design-Fähigkeit des Entwicklungsteams eine große Rolle spielen könnten. So können die Entwicklerinnen und Entwickler bei kleinen Applikationen etwa mit Leichtigkeit selbst den Funktionsumfang eines Features überblicken und durch Ausprobieren manuell testen, bevor die Tests nach der Entwicklung ergänzt werden.

Aber auch bei der Produktivität käme es auf das Team und dessen Erfahrung an, wie sehr sich jene steigern lässt. Da testgetriebene Entwicklung ein gewisses Grundverständnis benötigt und einer komplexen Implementierung bedarf, gelangen unerfahrene Entwicklerinnen und Entwickler zu einem geringeren Anstieg der Produktivität (Erdogmus et al., 2005). Die oben genannte anfängliche Verlangsamung könnte bei unerfahrenen Teams größer ausfallen.

Für testgetriebene Entwicklung ungeeignete Systeme

Aus den oben genannten Punkten lässt sich schließen, dass Test Driven Development nicht für jedes Projekt geeignet ist. Khanam und Ahsan (2017) erwähnen einige Beispiele:

Wenn das System Design zu Beginn der Entwicklung noch nicht klar ist.  Die Änderung des Designs während der Entwicklung würde eine ständige Überarbeitung und Anpassung der Tests an die neue Funktionalität bedürfen und damit in einem großen Zeitverlust resultieren (siehe auch: Dogša & Batič, 2011).

Nicht alle Systeme lassen sich an eine Testumgebung mit Unit Tests anpassen und es könnte mehr Zeit kosten, die Tests und das System aneinander anzupassen, als der Vorteil der Tests an Zeit und Qualität wieder einbringt. In solchen Sonderfällen ist also auch Vorsicht geboten. Jedoch sei laut Beck (2003) ein größerer Aufwand in der Implementierung der Testumgebung durch den Vorteil, den diese Testungen bringen, durchaus gerechtfertigt.

Wenn die gewählten Programmiersprachen und Frameworks keine sinnvollen Unit-Testing-Frameworks unterstützen, wird sich die Implementierung von TDD womöglich als schwierig herausstellen. Genauso ist die Testung von grafischen Userinterfaces deutlich schwieriger und zeitaufwändiger als die Testung von Libraries und APIs.

Wie bereits im Kapitel Produktivität genannt, kommt es auch auf die Erfahrung der Entwicklerinnen und Entwickler an. Nicht jede Entwicklerin bzw. jeder Entwickler ist ein erfahrener Test- und Refactoring-Experte. Dabei kann TDD die Produktion verlangsamen.

Khanam und Ahsan (2017) schlagen aufgrund dieser genannten Fälle vor, Test Driven Development beim Einbau an das System anzupassen und nicht das System so zu verändern, dass sich TDD anwenden lässt.

Fazit

Testgetriebene Entwicklung stellt, mit zahlreichen Belegen (Erdogmus et al., 2005; Khanam & Ahsan, 2017; Maximilien & Williams, 2003; Shull et al., 2010), eine Verbesserung für den Entstehungsprozess in Anbetracht von Software Qualität und Team-Produktivität dar. Es bedeutet im Entwicklungsprozess des Systems einen wiederverwendbaren und erweiterbaren Bestand an Tests zu generieren, der die Qualität des Software Systems über dessen Lebenszeit stätig verbessern wird (Maximilien & Williams, 2003). Der Anstieg der Software Qualität gegenüber der traditionellen Software Testung kann in wenigen der in dieser Arbeit beschriebenen Studien wie in der Pilotstudie von Erdogmus et al. (2005) nicht belegt werden, jedoch könnte dies laut Erstellerinnen und Erstellern und auch laut Khanam und Ahsan (2017) am Versuchsaufbau derartiger Pilotstudien zu diesem Thema liegen.

Im Einzelfall bedarf es womöglich einer Abwägung, ob Test Driven Development für die jeweilige Umgebung geeignet ist. Khanam und Ahsan (2017) nennen da einige Beispiele (siehe Kapitel 4 Ungeeignete Systeme). Für manche Projekte könnten andere ähnliche Methoden wie Behaviour Driven Development (BDD) oder Acceptance TDD (ATDD) passender sein.

Gerade der als größter Nachteil zu erwartende Zeitaufwand stellt sich zumindest bei erfahrenen Teams als Vorteil heraus, steigert die testgetriebene Entwicklung doch letztendlich die Produktivität des Teams (Erdogmus et al., 2005).

Testen trägt zur Qualität der Software und das Framework Test Driven Development zur Produktivität des Teams bei. Bei der Entscheidung über den Test-Last- oder den Test-First-Ansatz (wie in TDD) sind die jeweiligen Gegebenheiten des Projekts zu bedenken und sich für ein passendes Framework zu entscheiden. Jedoch ist eine ordentliche Integration von Testungen in den Entwicklungsalltag eines Produkts durch die zahlreichen oben genannten Vorteile in jedem Fall empfehlenswert.

Quellen

Astels, D. (2003). Test-driven development: A practical guide (3. print). Prentice Hall PTR.

Beck, K. (2003). Test-driven development: By example. Addison-Wesley.

Beck, K., Beedle, M., Van Bennekum, A., Cockburn, A., Cunningham, W., Fowler, M., Grenning, J., Highsmith, J., Hunt, A., Jeffries, R., Kern, J., Marick, B., Martin, R. C., Mellor, S., Schwaber, K., Sutherland, J., & Thomas, D. (2001). Manifesto for Agile Software Development. Manifesto for Agile Software Development. https://agilemanifesto.org/

Erdogmus, H., Morisio, M., & Torchiano, M. (2005). On the Effectiveness of the Test-First Approach to Programming. IEEE Transactions on Software Engineering, 1(31), 14.

Khanam, Z., & Ahsan, M. N. (2017). Evaluating the Effectiveness of Test Driven Development: Advantages and Pitfalls. 12(18), 12.

Maximilien, E. M., & Williams, L. (2003). Assessing test-driven development at IBM. 25th International Conference on Software Engineering, 2003. Proceedings., 564–569. https://doi.org/10.1109/ICSE.2003.1201238

Shull, F., Melnik, G., Turhan, B., Layman, L., Diep, M., & Erdogmus, H. (2010). What Do We Know about Test-Driven Development? IEEE Software, 27(6), 16–19. https://doi.org/10.1109/MS.2010.152

The comments are closed.