19.11.12 Argumente für automatische Tests

Investitionen in automatische Tests zahlen sich erst später aus?

Automatische Tests sind ein Segen. Aber trotz vieler Erfolgsgeschichten gibt es immer noch einiges an Skepsis. Vielleicht sind es aber auch Missverständnisse. Als Gründe, warum keine automatischen Tests eingesetzt werden, habe ich häufig zu hören bekommen, dass für automatische Tests keine Zeit vorhanden ist. Die Grundannahme dabei ist, dass sich die Investition in automatische Tests erst später in der Wartungsphase auszahlt.

Wenn die Zeit jetzt knapp ist oder eine Wartungsphase nicht vorgesehen ist, dann liegt es nah, die Zeit für automatische Tests zu sparen.

Automatische Tests sparen Zeit

Ich bin anderer Meinung (sonst wäre der Eintrag ja auch jetzt schon hier zu Ende) und versuche mal, ein paar Argumente für automatische Tests zusammenzutragen. Dies tu' ich in der Hoffnung, dass sie anderen hilfreich sein können, wenn sie wieder dem "Keine-Zeit"-Argument begegnen.

Bei den Argumenten versuche ich deshalb auch, besonders auf den Aspekt Zeit einzugehen und darzulegen, warum automatische Tests um so wichtiger sein könnten, je knapper die Zeit ist. Für weitere Argumente bin ich jeder Zeit dankbar und trage diese hier gerne nach.

1. Kürzere Build- / Start-Zeiten

Manuelle Tests werden in der Regel am fertigen Produkt durchgeführt. Das bedeutet: das komplette Produkt bauen, evtl. sogar installieren und komplett initialisieren beim Start. Im Gegensatz dazu werden die kompletten automatischen Tests eines Produkts üblicherweise auf mehrere, kleinere Programme verteilt. Diese Programme lassen sich vergleichsweise schnell bauen und starten.

Durch schnellere Schleifen durch den Implementieren/Prüfen-Zyklus, bleibt man länger fokusiert im Thema. Längere Wartezeiten lenken ab und laden zum Abschweifen ein, die Konzentration wird immer wieder durchbrochen.

Das setzt natürlich vorraus, dass Bau und Ausführung der automatischen Tests schnell gehen. Dazu sollte man die Build- und Laufzeiten seiner Testprogramme im Auge behalten. Aber selbst, wenn die Ausführung aller Tests eines Testprograms lange dauert, bieten die meisten Frameworks eine Möglichkeit an, gezielt nur einen Test oder eine Gruppe von Tests laufen zu lassen.

2. Wann ist eine Funktion eigentlich fertig?

Wenn einem die Zeit davon läuft und ein Lieferdatum wichtiger ist, als der komplette Funktionsumfang, wird man Abstriche beim Funktionsumfang machen wollen, wenn absehbar ist, dass der Gesammtumfang nicht zum Liefertermin leistbar ist. Hierzu ist es wertvoll zu wissen, wo man steht. Sind alle Funktionen wirklich zu 90% fertig, oder werden bei der abschließenden Integration noch erhebliche Aufwände sichtbar?

Ohne Einbetten in ein Testbett und systematisches Austesten einer Funktion kann keine Aussage über den Restaufwand bis zum fehlerfreien Funktionieren gemacht werden. Auf diese wichtige Information muss gewartet werden, bis die Umsysteme ebenfalls fertig sind und die manuellen Tests beginnen.

Diese Integrations-Tests finden meistens zum Ende eines Projekts statt. Werden nun unerwartet hohe Restaufwände für einzelne Funktionen sichtbar, ist bereits viel wertvolle Zeit in die Entwicklung dieser Funktionen geflossen. Diese Funktionen müssen nun aber unter Umständen trotzdem für den Liefertermin abgesagt werden. Wären diese Aufwände früher sichtbar gewesen, hätte man einzelne Funktionen bereits früher aus der Planung nehmen können und insgesamt einen größeren Umfang zum Liefertermin umsetzen können, indem man sich auf weniger Funktionen konzentriert hätte, von denen man dann aber sicher(er) wäre, dass diese zu 100% fertig werden.

3. Während der Entwicklung wird laufend getestet!

Ein Argument gegen automatische Tests ist die Annahme, dass sich der Aufwand für automatische Tests erst später amortisiert. Erst wenn nach Änderungen an der Software alle Tests immer wieder wiederholt werden müssen, zahlt sich die Investion in die Automatisierung der Tests aus. Muss die Software nur ein, zwei oder vielleicht drei Mal getestet werden, lohnt es sich nicht, diese Tests zu automatisieren.

Was wäre aber nun, wenn sich herausstellt, dass bestimmte Teile der Software von Anfang an laufend geändert werden? Iteratives Vorgehen verlangt, erst einmal eine Funktion fertigzustellen und nur das Minimum umzusetzen, das die Anforderungen erfüllt. Das ist mittlerweile ein gängiges Vorgehen, das aber auch dazu führt, dass Software während der Entwicklung laufend geändert wird. Um sicherzustellen, dass keine ungewünschten Änderungen an den bereits fertiggestellten Funktionalitäten vorgenommen wurden, müssen mit jeder Iteration auch die bereits vorher fertiggestellten Funktionen immer wieder getestet werden.

Spätestens, wenn beim abschließenden, manuellen Testen Fehler gefunden werden, und diese Fehler behoben wurden, muss die Software wieder getestet werden. Auch, wenn es so nicht immer in Projektplänen vorgesehen ist, wird Software vor der Auslieferung an den Kunden sehr häufig getestet. Hier kann man Zeit sparen, wenn man häufig wiederholte Tests automatisiert.

4. Einfachere Fehlersuche

Auch mit automatischen Tests wird man nie fehlerfreie Software erreichen. Aber wer regelmäßig automatische Tests einsetzt, kennt bestimmt folgende Situation:

Ein Fehler wird erst bei manuellen Tests oder vom Kunden gefunden. Ja, das ist ärgerlich! Erfreulicherweise ist durch das Vorhandensein von automatischen Tests klar, wo der Fehler nicht sein kann. Das schränkt den Aufwand bei der Suche erheblich ein. Ist der Fehler gefunden, schreibt man schnell noch einen Test, der den Fehler aufdeckt. Der Fehler wird behoben und das fehlerfreie Ausführen aller Tests bestätigt, dass nichts kaputt gemacht wurde und der Fehler behoben ist. Und damit ist das Thema erledigt.

Der Aufwand für das Schreiben des neuen Tests ist in der Regel wirklich klein, da die Infrastruktur schon vorhanden ist. Auf umfangreiche, manuelle Tests, die belegen, dass die Fehlerbehebung keine negativen Seiteneffekte hat, kann unter Umständen verzichtet werden.

5. Manuelles Testen ist nicht immer möglich / ausreichend

Nicht jede Software lässt sich von Außen, an den Schnittstellen, mit den vorhandenen Gegenstellen so mit Testdaten stimulieren, dass das nötige Vertrauen in Stabilität, Korrektheit und Performance endsteht. Teste ich einen Web-Server mit einem normalen Browser, dann lasse ich dabei z.B. außer acht, dass der Datenstrom zwischen Browser und Server beliebig fragmentiert werden kann. Ich kann damit auch nur "korrekte" Anfragen eines Browsers testen. Möchte ich korrektes Verhalten des Web-Servers bei ungültigen Anfragen testen, dann bleibt mir nur der Weg, einen Browser zu simulieren.

Möchte ich Software unter Last testen oder die Sicherheit gewinnen, dass multithreaded implementierte Software funktioniert, dann komme ich um automatisierte Lasttests nicht herum. Unterlasse ich diese Tests, laufe ich höchste Gefahr, dass nach Inbetriebnahme schwer reproduzierbare Fehler auftreten.

Fazit

Gerade, wenn die Zeit knapp ist, lohnt es sich, Ausschau nach den Tests zu halten, die sich einfach automatisieren lassen oder häufig durchgeführt werden müssen. GUIs gehören meistens eher zu den schlecht automatisiert testbaren Komponenten, während sich Parser und Generatoren z.B. besonders gut automatisch testen lassen.

Gibt es Funktionalitäten, die sich eh nur in einem Testbett aussagekräftig testen lassen, so können diese Tests genutzt werden (oder zum "Vorwand" genommen werden), die für automatische Tests notwendige Infrastruktur aufzubauen.

Investitionen in schnellere "Code - Compile - Test"-Zyklen können sich auch sehr schnell auszahlen, wenn man nicht nur die reine Zeitersparnis duch kürzere Build-, Start- und Test-Zeiten betrachtet, sondern auch ehrlich ist mit der Zeit, die man spart, wenn die während der Wartezeit beginnende Ablenkung, aber nicht unbedingt nach der Wartezeit endende Ablenkung wegfällt. (Den Artikel, den ich gerade angefangen habe zu lesen, lese ich dann auch zu Ende.)

Zusammenfassend gesagt, sollten automatische Tests bei knapper Zeit nicht kategorisch ausgeschlossen werden, sondern als Chance gesehen werden, durch Automatisierung Zeit zu gewinnen.