Eigentlich ist jedem bekannt: Software testet man, bevor sie live geht. Und jeder weiß auch um die Sinnhaftigkeit dieser Maßnahme. Trotzdem wird oft das Testen abgekürzt, wenn das Projekt in Zeitnot gerät. Testen wird plötzlich als Zeitfresser ohne entsprechenden Nutzen wahrgenommen. Doch was passiert, wenn man diese Abkürzung nimmt?
Technical Debt
Der Begriff Technical Debt mag einigen bereits bekannt sein, andere mögen ihn vielleicht schon wieder verdrängt haben. Ich möchte ihn noch einmal kurz erklären:
In dem Moment, in dem ein Entwicklungsteam einen Auftrag annimmt, befindet es sich in der Schuld.
Die Schuld wird aus den noch nicht umgesetzten Anforderungen erzeugt. Hierzu zählen neben der reinen Funktionalität auch Dinge wie Korrektheit, Robustheit, Verfügbarkeit und noch viel mehr schöne Dinge, die man auch als Software-Qualität bezeichnet und deren Vorhandensein durch automatisierte Tests sichergestellt werden kann.
Schuldenabbau
Dieser Berg an Schulden wird durch die Entwicklung Stück für Stück abgetragen, bis am Ende ein Stück Software entstanden ist, das allen Anforderungen
genügt. Soweit die Theorie.

Technical Debt bleibt bestehen, wenn man in der Entwicklung „abkürzt“
In der Praxis ist es dann doch leider so, dass man Zwängen unterliegt, die einem das vollständige und saubere Abtragen dieser Schuld erschweren. Zeit, Ressourcen und Kollegen sind selten in der benötigten Menge und Qualität verfügbar oder werden während der Entwicklungszeit gekürzt bzw. abgezogen. Kurzum, man ist nicht in der Lage, den ganzen Berg abzutragen, ohne den Rahmen des Projekts zu sprengen. Oftmals wird in so einer Situation entschieden, auf Tätigkeiten zu verzichten, die scheinbar unproduktive Zeitfresser sind: Dokumentation und Tests.
Dass dies zudem die Tätigkeiten sind, die den meisten am wenigsten Spaß bereiten, ist dabei auch kein Zufall. Selbsterklärende Quelltexte schreibt ja jeder, wozu also noch dokumentieren, was eh schon leicht verständlich im Code steht? Und die fehlenden Tests braucht man – seien wir ehrlich – doch auch nur einmal am Ende durchzuführen, um dem Ganzen den letzten Feinschliff zu geben.
Die Gefahr der Abkürzung
Was man leider leicht übersieht und meist auch erst glauben mag, wenn man sich genügend an dem Thema verbrannt hat, ist die unangenehme Wahrheit, dass man nichts von alledem weglassen kann – vorausgesetzt, man hat es vorher nicht übertrieben, aber KISS und YAGNI sind nicht Thema dieses Beitrags.
Natürlich kann man aus dem Quelltext entnehmen, WAS ein Stück Code tut. Man erkennt aber nicht, WARUM es das auf diese Art und Weise tut – und, um wirklich ehrlich zu sein, die Frage nach dem Warum (auch gerne als WTF? formuliert) ist doch eine der am häufigsten gestellten beim Code Review, oder? Also bitte, ein jeder sollte sich selbst und seinen Kollegen (besonders den zukünftigen) einen Gefallen tun, und die vermurksten weniger leicht verständlichen Code-Stellen so dokumentieren, dass man später noch weiß, warum es dort so aussieht. Und wenn es nur ein ehrliches „Ich weiß nicht warum, aber es funktioniert“ ist.
Aber warum noch mal soll man Doku hinterlassen? Tut man’s nicht, ist der Code schwerer veränderbar. Veränderbarkeit ist aber Grundvoraussetzung für agile Projekte, für Wartbarkeit und spätere Weiterentwicklung. Was ist am Ende schlimmer? Kundenwünsche nicht oder nur unter finanziellem Verlust umsetzen zu können oder über die Entwicklungszeit hinweg etwas Doku geschrieben zu haben?

Auch Kleinvieh macht Mist: Technical Debt häuft sich über mehrere Iterationen zu einem Schuldenberg an.
Schauen wir mal rüber zu den Tests. Der Gedanke, es würde reichen, einmal am Ende des Projekts alles durchzutesten und gegebenenfalls Bugfixes vorzunehmen, ist ein großer Irrtum. Unterstreichen wir mal die Worte einmal und alles. Wartet man mit der QS bis zum Ende und führt man sie dann gründlich durch, kann man nochmal mindestens das an Zeit hinten ‚ranhängen, was man durch das Abkürzen gespart hat. Mindestens bitte auch unterstreichen.
Das Problem mit dem Nicht-Testen sind nicht die kleinen scharfkantigen Rückstände an den Rändern oder winzige Toleranzen im Millimetermaß, sondern die ganzen kleineren und größeren Designfehler, die man erst beim Zusammensetzen bemerkt.
Designfehler am Ende noch einmal schnell beheben? Das funktioniert nicht. Nur wenn man sie frühzeitig entdeckt, behebt und aus ihren Ursachen lernt, um sie danach zu umgehen, vermeidet man, in diese Sackgasse zu geraten.
Ist es wirklich so schlimm?
Ja. Leider. Mir ist mindestens ein Entwicklungsteam bekannt, das just eine derart große Bugwelle vor sich herschiebt, dass womöglich ein weiterer Sprint vonnöten ist, um das geplante Release fertigzustellen. Natürlich wären sie auch nicht viel früher fertig, wenn sie „alles richtig“ gemacht hätten, aber darum geht es nicht. Der Punkt ist, dass das Problem erst jetzt, in der Mitte des Projekts, allen Beteiligten auf die Füße fällt. „Immerhin schon so früh“, werden jetzt vielleicht manche denken, aber wäre das Problem früher transparent gemacht worden, hätte man auch früher gegensteuern können. Symptomatisch erkennt man diese Bugwelle übrigens an dem leicht, aber stetig steigenden Verhältnis von Restanten aus dem letzten Sprint zu neuen Storys. Auch die nicht mehr funktionierenden Integrationstests sind ein weiteres Symptom, das deutlich auf Debt hinweist.
Nun weiß ich aber auch, dass es nicht am Können oder Wollen der Einzelnen oder des Teams liegt. Hier spielen äußere, hemmende Einflüsse eine große Rolle.
Und die Moral?
Regelmäßiges Testen und sinnvolles Dokumentieren der eigenen Arbeit entfalten ihre Wirkung zwar erst spät, sind deswegen aber kein unnötiger Ballast, sondern Notwendigkeiten, um ein Projekt erfolgreich durchzuführen und abzuschließen.
Test und Dokumentation sind auch keine Einwegprodukte, die nach der ersten Verwendung entsorgt bzw. liegengelassen werden können – auch wenn sie zugegebenermaßen langsam bis zum DELETE verrotten ;)
Das Thema Continuous Integration/Delivery kommt hier sofort in den Sinn. Nächtliche Builds sind ein Anfang, fortwährendes Verteilen von vollständig automatisiert getesteten Softwarekomponenten auf Produktion ist das Ziel. Aber CI alleine schafft noch keine Qualität – dafür braucht es Qualitätsbewusstsein als gelebten Wert im gesamten Unternehmen. Und das ist dann auch leider zu häufig die Wurzel des Übels. Jeder will Qualität, möchte dafür aber nichts tun oder geschweige denn etwas verändern. Wenn Technical Debt leichtfertig akzeptiert wird, muss erst ein Wertewandel stattfinden, bevor unterstützende Maßnahmen wie CI richtig greifen können.
Ach Du sprichst mir so aus der Seele…. vielen Dank für den Beitrag, ich habe einen Link darauf gleich massenweise verteilt. Am Ende sind es so oder so die Entwickler, welche die Probleme von unter Zeitdruck umgesetzte Projekte und die dabei unter den Tisch gefallenen Pflichten irgendwie ausbaden dürfen.
Hallo,
ja Qualitätsbewusstsein, das ist eine Eigenschaft, die sicher eine ganze Menge Entwickler haben. Die würden dieses Bewusstsein auch gerne Leben, aber sie dürfen es nicht, weil Cheffe sagt „Wir brauchen nicht 150% zu entwickeln! Wann seid ihr endlich fertig??“, obwohl es in Wahrheit nur vielleicht 80-90% sind. Viele Firmen, die Software entwickeln sind so hoffnungslos unterkapitalisiert, die können und wollen sich gar nicht Qualität leisten. „Bananensoftware“ ist da das Stichwort. Es reift das Programm beim Anwender. Firmen fahren so die Zeckentaktik: Festbeissen und Saugen. Bloß nie mehr machen als der Kunde unbedingt fordert. Will er mehr haben, muss er zahlen und das eben und besonders auch für Qualität.
Wer Qualität fordert, so finde ich, sollte zuerst beim Management dafür grünes Licht einfordern und den Managern sagen, dass das höchstwahrscheinlich auch zu höheren Kosten führen wird. Den Entwicklern ist das meist schon klar, dass wenn an Tests und Dokumentation gespart wird, dass das über kurz oder lang zu Problemen führt.
Hallo,
diesen Beitrag halte ich für gut, vielen Dank.
Folgende Fragen:
Werden beim agilen Testen noch Testfälle verwendet, die auf Basis von Use Cases beschrieben sind? Ich denke, dass das strukturierte Testen auch notwendig ist, sonst ist eine Ermittlung der Testüberdeckung nicht mehr möglich. Nur exploratives Testen ist aus meiner Sicht nicht ausreichend, wie auch nur das Testen von User Stories und deren Acceptance Criteria.
Welche Testobjekte sind beim agilen Testen gefordert?
Wie bestimmen wir die Testüberdeckung beim agilen Testen?
Hallo,
völlig richtig ist, dass es nicht damit getan ist, Features isoliert zu testen. Mindestens ebenso wichtig ist das integrative Testen mehrerer Features im Zusammenspiel
Wenn ich Ihre frage richtig verstehe, zielen Sie darauf ab, wie man das mit agilen – um beim Scrum-Sprachgebrauch zu bleiben – Story-getriebenen Vorgehen vereinbar ist. Features werden auf Stories abgebildet, deren Funktionsweise durch die Akzeptanztests der Story gesichert ist. Nun folgt die Integration ja auch einem Ziel und kann auch als Story formuliert werden. Diese Story ist dann äquivalent zu dem von Ihnen angesprochenen Use Case und ihre Akzeptanztests sind die oben erwähnten Integrationstests.
Um die dadurch entstehenden hierarchischen Abhängigkeiten zwischen Stories nicht aus den Augen zu verlieren, kann man sie als Story-Map visualisieren. In einem aktuellen BPM/SOA-Projekt haben wir die Stories entlang der Prozesse angeordnet. So gewinnen wir gleichzeitig einen Überblick über die Testabdeckung.
Ich hoffe, dass Ihnen einen Denkanstoß geben konnte und freue mich auf weitere Diskussion!
Viele Grüße,
Stefan Zilske
Hallo Dietrich,
dass Qualität zu höheren kosten führt, würde ich so nicht unterstreichen. Das ist zwar richtig, wenn man nur die erstmalige Entwicklung betrachtet, aber der Kunde wird spätestens dann, wenn er das System einsetzen darf, fehlende Qualitäten bemängeln und Nachbesserung verlangen. was natürlich auch Kosten verursacht.
Eher ist es doch so, dass eine nachträgliche Qualitätssteigerung teurer wird, als angemessene Gründlichkeit bei der initialen Entwicklung.
Am Ende sind die Gesamtbetriebskosten höher, wenn man an allen Ecken und Enden spart.
Viele Grüße,
Malte