"Einfach so mit Tests starten"

„Einfach mal anfangen“ ist schon lange mein Kredo wenn es um testgetriebene Entwicklung und automatische Tests geht. Seit nunmehr über 10 Jahren bin ich in Legacy Anwendungen und deren Code unterwegs. Es stellte sich also nie die Frage „Machen wir bei unserem neuen Projekt automatische Tests?“. Nein, die gabs nicht und keiner nimmt sich Zeit diese einzuführen. „Wenn wir mal Zeit haben und keine Tickets, dann gucken wir uns das mal an.“. Und „Bugfixing hat Vorrang!“. Hm, Nicht. Sondern so: Einfach mal anfangen!

Im aktuellen Projekt gibt es 100k+ Zeilen Code, tausende Templates, Controller, hunderte Models mit Tonnen undokumentierter Geschäftslogik und Sonderlocken. Das alles funktioniert erstaulich gut, auch ohne Tests! Also warum „einfach mal“ damit anfangen?

Schonmal versucht, ein nicht dokumentiertes Modul in einen komplexen System zu refaktorisieren? Weiß man, was diesen und jener Controller/Seite wirklich im Detail in jeder Situation tut? Nicht wirklich, deswegen wird es nicht angefasst, und wenn dann minimalinvasiv „ergänzt“ (=rangepappt) oder aber nach stundenlanger Analyse ein Bug gefixt. Dann testet man die neue Anpassung/den Fehler durch und gibt das Produkt auf Sendung. Und dann wächst die Legacy Anwendung immer weiter und macht der Bezeichnung „Legacy“ alle Ehre. Nicht das sie schlecht läuft, aber Redesign und Refaktorisierung ist praktisch nicht möglich.

Mit automatischen Tests kann man schrittweise den Code umgestalten, und immer wieder mittels schnell durchzuführender automatischer Tests die Korrektheit prüfen.

Jede Stunde die in automatische Tests investiert wird bekommt man mindestens doppelt zurück.

Testen rechnet sich! Folgendes Diagramm zeigt die wieviel Zeit man verbringt mit und ohne Test.

testen_rechnet_sich

Einfach mal anfangen… aber Wo, Wie, Wer, Wann, Was? Ein Vortrag auf der DC2013 greift genau diesen Aspekt auf und spannt den Bogen vom Vorsatz bis zur Einführung – und gibt dabei detailreich Auskunft. Der vorliegenede Artikel versucht ein Transkript zu sein und notiert die wesentlichen Punkte – ohne Anspruch auf roten Faden oder Vollständigkeit. Das Video sollte man sich bei tieferen Interesse auf jeden Fall ansehen!

Transkript zu DevCon 2013 Vortrag von Judith Andresen und Arne Blankerts auf der Developer Conference 2013

 

Testen rechnet sich!

testen_rechnet_sich

Diagramm basiert u.a. auf Microsoft, die die damalige Einführung von automatischen Tests stark gemonitort haben.
bzgl. Testlevels: es ist 150x teurer einen Test in einen Livesystem zu finden, als ihn in den fachlichen Anforderungen (User-Stories, Pflichtenheft) zu identifizieren
je tiefer man testet (unit-tests statt akzeptanz-tests), desto geringer ist die komplexität der Anforderungen

Es macht mehr spaß neue Features zu bauen und Tests zu schreiben als in einen „Big Ball of Mud“ herumzustochern.

Qualität ist nicht absolut

Was rechnet sich in unserem Kontext?
Kosten Testerstellung vs. Bugfixing-Aufwand

Qualität misst sich für den Endverbraucher hauptsächlich in der GUI, der Kontext des Betrachters entscheidet.
Für Vorstände ist ein Kommafehler im Text oder nicht eingehaltene CI-Vorgaben ein Projektproblem

Wieviel Qualität brauche ich eigentlich? Und wo?
100% Test-Coverage braucht man nur für Flugzeug-Autopiloten und Mondflüge.

Vorgehen zur Einführung

Auf ein Bier/Wein treffen mit QS, und in lockerer Atmosphäre fragen „Was kann denn hier alles schief gehen?“
Zunächst kommen relativ einfache Vorschläge, später dann lustige Vorschläge und Anekdoten vergangener Fälle.
Daraus Risikomatrix erstellen mit Fehlertypen
Wie kann man diese Typen am besten absichern?
testmatrix

Diese Treffen kann man regemäßig machen und fortschreiben (ggf. ohne Bier/Wein).
Regelmäßig gucken was waren für Fehlerfälle, auf welcher Ebene sollten wir die abprüfen (Unit-Tests, Akzeptanz-Tests, User-Tests)
Nicht jeder Fehler muss sofort in ein automatisiertes Testverfahren, das ist zu teuer.
Besser agile Regel „rules of three“ nutzen: Wenn ein Fehler(-szenario) zum dritten mal auftaucht in einer bestimmten klasse, dann sollte ich mich drum kümmern, sonst ist es „Fernwirkung“.
Ziel: Testklassen finden und Testleveln nähern

Für jede neue Anforderung gleich fragen:
Wer testet das zum schluss, und auf welchem Level?

Voraussetzungen

  • Geplante Lebensdauer?
  • Welche Risiken gibt es?
  • Wie hoch sind diese?
  • Was ist das Geschäftsmodell?

Lebensdauer ermitteln für intern entwickelte Software: entspricht mindestens dem Abschreibungszeitraum für die Entwickleraufwände.

Risiken: Zeit für den Bierabend.
Wie teuer ist der Fall wenn er eintritt? Gehe ich das Risiko ein oder ist es billiger mich dagegen abzusichern? Das kann man interdisziplinär im Team beantworten.
-> Testen ist eine Form von Versicherung
Zu investierende Arbeitszeit vs. wahrscheinlicher (Image)Schaden und Nachbeben
z.B. es besteht die Gefahr, Dinge aus der Testumgebung in die Produktivumgebung zu übernehmen (Debuggig-Weichen, -Kommentare, fest überschriebene Testwerte); Wie sichere ich mich dagegen ab?

Geschäftsmodell eigentlich: z.B. Autovermietung: Gebrauchtwagenverkauf, Pizzabestellung: Lastspitze bei EM/WM Halbzeit verkraften, Axilaris Obelisk: Onlinebanking 100% stabil betreiben
-> Um was geht es eigentlich?

Einführung

Wieder zusammensitzen:
Was ist das wesentliche? Was ist der Kern? „Wenn das und das schiefgeht ist das ganz schlimm“ -> dort sollte man anfangen
Wer ist für welchen Test zuständig?

Checkliste

  • Geschäftsmodell verstehen
  • Ziele des Testens klären
  • Testprozesse und -ebenen
  • Mit dem Wichtigsten anfangen

„Wichtigsten“ -> im Team (Entwickler, Marketing, Grafiker, Manager, GF, Vorstände) beantworten

Fazit

Einführung von automatischen Tests ist in erstes Linie ein interdisziplinäres Thema, welches bei der Einführung firmenweit abgestimmt werden muss, und welches im hohem Maße ein Kommunikativer Prozess ist. Das bedeutet, dass auch wir als Entwickler viel reden und reflektieren müssen. Auch unangenehme Dinge wie personenspezifische wiederkehrende Fehlerbilder werden besprochen werden müssen. Am Ende etabliert sich aber ein Qualität steigernder und sichernder Prozess, der die gesamte Firma und auch das Produkt (unser aller Code und Anwendung) auch im Legacy-Umfeld mit Lebensdauer von 10+ Jahren überlebensfähig macht. Und am Ende haben wir als Entwickler wieder mehr Spaß an der Arbeit, was man dann der Anwendung anmerkt. Und dafür lohnt es sich zu kämpfen!