Aus dem Blog

Golo & Götz (06)

von Götz Martinek

"Golo & Götz" ist eine gemeinsame Serie von Golo Roden und Götz Martinek. Der eine ist CTO von the native web GmbH, der andere Geschäftsführer von sodge IT GmbH. Was die beiden vereint, ist ihre große Leidenschaft für die Entwicklung von Software. Seit September 2019 nehmen sie sich monatlich ein Thema vor, zu dem dann jeder seine individuelle Perspektive beschreibt, ohne den Artikel des jeweils anderen im Vorfeld zu kennen. Der zugehörige Artikel von Golo findet sich in seinem Blog auf heise.de/developer.

Die Fragestellung zu diesem Beitrag lautete: "Günstigere Software durch weniger Tests?"

Günstigere Software durch weniger Tests?

Wenn man sich etwas ältere Projekte ansieht, fällt einem oft auf, dass zu Beginn eines Projektes immer Zeiten für den Test eingeplant werden. Meistens wurde diese Testphase gegen Ende des Projektes eingeplant. Grund war eine Entwicklung basierend auf dem Wasserfallmodell, und man will ja schließlich nur funktionsfähige Software rausgeben, also testet man vor dem Release.
Interessanterweise wurden diese ursprünglich eingeplanten Testzeiten meist nie so gehalten wie geplant. Am Ende wurde die Zeit für das Testing durch jede Verzögerung während der Entwicklung verkürzt.
Der Grund: Eine Verzögerung des Releasezeitpunktes kam auf keinen Fall in Frage. Dass einige Verzögerungen in der Umsetzung gegebenenfalls durch einen etwas kleineren Funktionsumfang ausgeglichen werden hätten können, um dem Test so wieder die Zeit zu geben, die er eigentlich benötigt, stand leider meist außer Frage.
Frech gesagt, wurde die Testzeit eigentlich nur als Puffer genutzt, und um günstig Software zu entwickeln, wird am Ende gespart.
Leider wird heutzutage stellenweise immer noch so entwickelt.

So etwas ist sehr unzufriedenstellend und demotivierend für die involvierten Tester. Eine echte Wertschätzung ihrer Arbeit erfahren die Tester so nicht.
Ein erfahrener Tester sagte mir allerdings auch einmal: "Früher hat mich das aufgeregt. Heute weiß ich, wenn was wegen Zeitmangel nicht getestet wird, dann kommt das wieder ... und dann bekommt es seine Zeit."
Das klingt nach Resignation, ist aber die einzige Möglichkeit, um weiterhin seinen Aufgaben nachkommen zu können, ohne sich daran aufzureiben.

Mit diesem Wissen, dass die endgültig verbleibende Zeit nicht ausreichen wird, kann ein guter Tester auch die kritischeren Funktionen mit höherer Priorität testen. Er weiß ja schließlich, dass ihm die Zeit beim ersten Durchgang sowieso ausgehen wird. So kann er die wirklichen Blocker gegebenenfalls schneller finden, und die "Nice to have"-Features können später nachgereicht werden.
Diese Art der "Problemumschiffung" hängt aber stark davon ab, wie einfach spätere Updates ausgerollt werden können und für welchen Einsatzzweck die Software gedacht ist.

Kann man diesem Muster entfliehen?

Oft wird, um dem oben beschriebenen Muster zu entfliehen, der Weg in Richtung "weniger Releases pro Zeiteinheit" eingeschlagen. Was im Endeffekt meist dazu führt, dass die gleichen Probleme nur in größerem Umfang auftreten.
Der Druck, den gesetzten Termin für ein Release einzuhalten, wird immer größer, denn wenn wichtige Fixes oder Features nicht in das geplante Release kommen, müssen Kunden immer länger auf ihr Update warten.
Meiner Meinung nach ist der beste Weg, um dem Dilemma zu entkommen, sich in Richtung "Continuous Delivery" zu bewegen. Also nicht weniger releasen, um dem oben genannten Muster zu entkommen, sondern mehr Releases. So erhält man schnelle Reaktion auf Anforderungen – egal ob neue Features oder Bugfixes – und damit zufriedenere Kunden.

Wie kann man sich auf den Weg begeben?

Die Schritte zum Release werden größtenteils automatisiert und auch regelmäßig gemacht, was wiederum die Fehlerquote der menschlichen Tätigkeit reduziert. Als Grundlage auf Entwicklerseite sollten definitiv automatisierte Unittests und automatisierte Integrationstests sein. Damit lassen sich aus Entwicklersicht viele Dinge auffinden, vor allem, was Fehler bei Änderungen am Code angeht. Zusätzlich stärkt es das Vertrauen der Entwickler in den selbst entwickelten Code. Was zu ruhigerem Vorgehen bei Releases führt und zu entspannteren Nächten, vor allem in der Übergangszeit vom alten zum neuen Vorgehen. Mit dem passenden Toolset hilft die Automatisierung bei der Eingrenzung von Fehlern, die vom Test gemeldet werden.

Mit steigender Anzahl an Tests, die bei jedem Commit ausgeführt werden, leidet allerdings die Ausführungszeit der Builds. Ein kompletter Durchlauf bei jeder Codeänderung ist einfach nicht mehr sinnvoll möglich. Ein "Abklopfen" nur bestimmter Tests kann den Entwicklungsprozess hier wieder beschleunigen und dem Entwickler schnell Feedback zu seinen Änderungen geben.
Dieses Abklopfen will Kohsuke Kawaguchi, CTO von cloudbees und Entwickler von Hudson/Jenkins, mit seiner neu gegründeten Firma Launchable ermöglichen. Ziel soll es hier sein, nicht mehr alles vollständig bei jedem Commit zu testen, sondern nur die durch die aktuelle Codeänderung "vermutlich" betroffenen Bereiche.

Für den Tester wiederum ergibt sich durch den Einsatz vieler automatisierter Tests die Möglichkeit, sich auf die deutlich komplexeren und ausgefalleneren Tests zu konzentrieren. Er hat sozusagen wieder Zeit fürs Testen erhalten.
Ein weiterer Vorteil ist, wenn diese Zeiten bei Abschätzungen direkt mit in die Entwicklungszeit fließen, dann können sie später schlechter als Puffer herhalten und damit sozusagen gestrichen werden. Eine minimalistische/kurze "Definition of Done" hilft hier, den inneren Schweinehund zu überwinden und sich selbst und das Team immer auf fehlende Unittests hinzuweisen.
Als Nachteil muss – fairerweise – der erhöhte Aufwand in der Entwicklung genannt werden. Allerdings ist die Aussage, der Testaufwand sei so zu hoch, meiner Meinung nach eine Ausrede. Hierbei ist dann meist faktisch der Aufwand für das Testen, egal wo er eingeplant wurde, zu gering abgeschätzt.

Muss ich jetzt TDD machen?

Test Driven Development (TDD) ist ein toller Ansatz, muss es aber nicht unbedingt sein. Bei TDD soll, kurz gesagt, zuerst der fehlschlagende Testfall geschrieben und dann erst die entsprechende Funktion implementiert werden, um sich iterativ dem Endergebnis anzunähern. Wenn man sich daran gewöhnt hat, ist das nicht viel langsamer, als Tests zeitnah nach dem Code zu entwickeln. Was TDD aber zusätzlich mit sich bringt: Es ist ein wirklich fabelhaftes Mittel, um sich seiner API und Nutzung seines frisch implementierten Codes bewusst zu werden.
Für den Anfang ist es schon ein riesiger Schritt in die richtige Richtung, wenn einheitlich Unit- und Integrationstests in den Projekten vorhanden sind.

Fazit: Software wird durch eingesparte Tests nicht günstiger!
Die Lösung ist nicht mehr oder weniger Testen am Ende, sondern öfters zwischendurch!

Zurück