Hin und wieder kommt man als Consultant in die Situation, das Schreiben automatischer Tests begründen zu müssen. Meistens sind das genau diese kritischen zehn Minuten, die einen gewaltigen Impact auf die nächsten zehn Monate des Projekts haben. Und Gründe gegen automatisierte Tests kennen wir alle …
„Wir haben keine Zeit, um Tests zu schreiben – schreibt sie doch hinterher!“
„Wir haben hier Crunchzeit und müssen uns darauf konzentrieren, Features zu liefern.“
Ich fasse hier die wirkungsvollsten Argumente zusammen, die ich in zehn Jahren Softwareentwicklung gesammelt habe. Die Sammlung ist nicht vollständig – ich bin hier immer für Ergänzungen dankbar! – und die einzelnen Argumente sind auch nicht in jeder Situation angemessen. Mir haben sie bis jetzt jedoch als gute Grundlage gedient.
Sie sparen Geld
Ich bin hier voll und ganz einer Meinung mit Martin Fowler – das einzige Argument das zieht ist: Sie sparen Geld.
Nicht „das macht man halt so“, nicht „mein handwerklicher Stolz gebietet es“, nicht „es führt zu hübscherem Code“. Jedesmal wenn ich meine Argumentation so begonnen hatte, stand ich auf verlorenem Posten.
Warum sparen automatische Tests Geld?
… oder auch: “6 bombenstarke Argumente für Tests, Nummer 1 wird Dich umhauen!”
Ausgezeichnete Frage! Im folgenden Liste ich die Hauptpunkte.
1. Möchtest Du, dass Deine Feautures in zehn Stunden oder in zehn Tagen fertig werden?
Dahinter steckt das Prinzip des furchtlosen Refactorings, das eine gute Test-Suite ermöglicht. Wenn ich argumentiere, benutze ich das Wort Refactoring grundsätzlich nicht. Refactoring klingt für viele wie Türgriffe polieren, Arbeit ohne erkennbaren Business Value. Stattdessen sage ich folgendes:
Tests ermöglichen es, radikale Codeänderungen durchzuführen ohne Angst davor zu haben, etwas kaputt zu machen. So kann man sich auf automatische Tools verlassen, die diese Änderungen schneller und besser durchführen, als ein Mensch es kann. Das spart unglaublich viel Zeit. Die Taktik ist hier: Den Code so zu restrukturieren, dass die gewünschten Änderungen nur noch wenige Codezeilen benötigen. Das geht erheblich schneller, ist sehr viel einfacher zu reviewen und weniger anfällig für Bugs.
Man läuft hier in eine sogenannte „emergente Architektur“. Vereinfacht und auf Deutsch heißt das, dass der Code immer angemessen strukturiert ist, um die wahrscheinlich eintreffenden Änderungen schnellstmöglich durchführen zu können.
Zitat Ende. Das ist das Kronjuwel meiner Argumentation. Ich rattere aber gerne noch die anderen Vorteile hinterher, um meinen Punkt zu untermauern. Ich ordne sie hier wieder in absteigender Stärke (meiner super subjektiven Einschätzung nach).
2. Selbstdokumentierender Code
Ein Test sagt sehr genau, was in welcher Struktur in eine Funktion übergeben wird und wie das Ergebnis aussehen soll. Das spart Dokumentationsaufwand, für den man oft im Alltagsgeschäft keine Gelegenheit hat, weil sich Dinge einfach zu schnell ändern.
Programmierer verbringen außerdem – Robert C. Martin’s Daumenregel folgend – zehnmal so viel Zeit, Code zu lesen als ihn zu schreiben. Hier optimieren wir also am Bottleneck.
3. Bugs fixen, wenn man drin ist
Je schneller ich darüber informiert werde, dass etwas kaputt gegangen ist, desto billiger kann ich es reparieren. Wenn ich eine Zeile ändere, meine Tests ausführe und sie rot werden, finde ich meinen Fehler sofort.
Wenn ein merkwürdiger Bug jedoch in zwei Monaten auffällt, kann es Tage dauern, ihn zu reparieren.
4. Bessere Kommunikation
Gut benannte und strukturierte Tests kann ich einem Stakeholder zeigen und meine Annahmen kommunizieren. Was gilt es wirklich zu tun, wenn Formularfeld X leer ist?
Ich gehe selten mit Nicht-Techies durch die tatsächlichen Tests durch, aber oft finde ich so die richtigen Fragen, die ich stellen muss, an die man sonst nicht denkt. Und das führt mich zu …
5. Edge Cases bedenken
Entwickler, die sich selbst die Frage stellen, was man in Edge Cases eigentlich tun sollte
- Was, wenn die Eingabe leer ist?
- Was, wenn die Verbindung unterbrochen wird?
… haben schon viele Eisberge umschifft, bevor sie teuer wurden.
6. Bugs finden, bevor sie auftreten
Wenn ich eine gute Test-Suite habe, werden auch Komponenten die für ein paar Monate in Ruhe gelassen werden, regelmäßig getestet. Wie teuer ist es, wenn kritische Bugs auftreten, die die App lahm legen? Und selbst wenn das okay sein sollte, würde man die Bugsuchzeit nicht lieber in Feature-Entwicklung stecken?
Einen guten Abschluss wählen
Ich mag es, diese Argumentation mit einem Ausblick zu beenden.
Auf fast jeder Softwarekonferenz findet man einen Vortrag über TDD und Architekturvorträge leiten ihre Refactorings gerne mit der Erwähnung von Tests ein. Das Thema hat in den letzten Jahrzehnten und Jahren immer mehr Akzeptanz gefunden.
Sicher ist es etwas, das man in Moderation machen muss – mit klarem Blick auf die Kosten und Nutzen. Unterm Strich fährt man meiner Erfahrung nach aber mit Tests astronomisch besser als ohne.
Fazit
Wie ich schon sagte, sehr subjektiv und stark vereinfacht: Es ist meine starke Meinung, dass man als Berater – aus Verantwortung dem Kunden gegenüber – eine starke Meinung vertreten muss. Diese Meinung gut begründen zu können und Argumente parat zu haben, kann einen Impact haben, den man nicht unterschätzen sollte.
Eine Bitte noch zum Abschluss …
Bitte schreibt gute Tests!
Die klassischen Akronyme FIRST (Fast, Independent, Repeatable, Self-Validating, Timely – die Eigenschaften eines guten Tests) und AAA (Arrange, Act, Assert – die Struktur eines guten Tests) sollte man kennen.
Eine gute, pragmatische Mischung aus Unit-Tests (einzelne Methoden eines konkreten Objekts) und Integrationstest (Funktioniert die App als ganzes?) gilt es zu finden.
Und wenn ein Stück Code schwierig zu testen ist, könnte es daran liegen, dass man ihn besser strukturieren könnte? Lose gekoppelt? Mit getrennten Verantwortungen in jeder Klasse?
Wenn man dem Kunden schon sauberes Arbeiten erfolgreich verkauft hat, dann gilt es auch, sauber zu arbeiten!
In diesem Sinne … happy testing!
Schreibe einen Kommentar