Die “Heisenbergsche” Testunschärfe bei automatisierten Testwerkzeugen

Kritische Fehler, die erst im Rahmen des Live-Betriebs öffentlich werden, stellen eine negative Werbung für ein Produkt und die beteiligten Unternehmen dar. Um dies zu verhindern, ist das Thema Testautomatisierung in der modernen Softwareentwicklung ein grundlegender und integraler Bestandteil. Durch die technische Umsetzung mit Testautomatisierungswerkzeugen entstehen aber Probleme, denen wir uns bewusst sein müssen.

Nur durch eine hohe Testabdeckung und der zeitnahen Rückmeldung von Ergebnissen lässt sich die Qualität und Reife des Produktes ausreichend genau nachweisen und bestätigen. Dabei werden von den Beteiligten verschiedene Testvorgehen und Testarten eingesetzt, wie automatisierte Codeanalyse oder automatisierte Unittests durch die Entwickler sowie automatisierte Oberflächentests durch die Tester. Für die unterschiedlichen Testarten wurde bereits früh versucht, übergreifende Kategorien zu finden, wie zum Beispiel die Abgrenzung in Black-Box- und White-Box-Tests.

Laut dem German Testing Board (Archivversion 2.1 des ISTQB® GTB Glossary) versteht man unter Black-Box-Testen “funktionales oder nicht-funktionales Testen ohne Nutzung von Informationen über Interna eines Systems oder einer Komponente” und unter White-Box-Testen einen „Test, der auf der Analyse der internen Struktur einer Komponente oder eines Systems basiert“. Bis vor ein paar Jahren ließen sich Black- und Whitebox-Testverfahren fast synonym zu zwei anderen Einteilungen benutzen: dem dynamischen Test, der „Prüfung des Testobjekts durch Ausführung auf einem Rechner“, und dem statischer Test, dem „Testen von Software-Entwicklungsartefakten, z.B. Anforderungen oder Quelltext, ohne diese auszuführen, z.B. durch Reviews oder statische Analyse“. Heute lässt sich diese Unterscheidung nicht mehr treffen, da Unit-Tests oder Testvorgehen wie Test-Driven-Development (TDD) die eigentliche Abgrenzung zwischen White- und Blackboxtests aufgelöst haben. Ich bezeichne den neuen Bereich als “Grey-Box-Test”. Die Grey-Box-Tests versuchen, erwünschte Vorteile von Black-Box-Tests (spezifikationsgetrieben) und White-Box-Tests (entwicklergetrieben) weitestgehend miteinander zu verbinden und gleichzeitig die unerwünschten Nachteile möglichst zu eliminieren.

Der Vorteil ist, dass Teilkomponenten und Gesamtsysteme mit dem geringen organisatorischen Aufwand der White-Box-Tests geprüft werden können, ohne eventuell “um Fehler herum” zu testen. So werden bei TDD die Komponententests anhand der Spezifikation vor der eigentlichen Entwicklung des Codes erstellt. Die Entwicklung der Komponenten wird erst abgeschlossen, wenn alle Prüfroutinen erfolgreich durchlaufen wurden. Neben den Vorteilen gibt es aber auch ein paar wichtige Aspekte zu beachten. TDD bzw. die Grey-Box-Tests erfordern eine hohe Disziplin, damit diese praktikabel und erfolgreich eingesetzt werden können. Aber viel wichtiger ist der Punkt, dass Grey-Box-Tests nicht unbedacht als vollwertiger Ersatz für Black-Box-Tests gesehen werden sollten.

Warum sollte man sich nicht nur auf automatisierte Grey-Box-Tests verlassen?

Grey-Box-Tests verändern und beeinflussen das System, das sie prüfen sollen. Dieser Aspekt ergibt sich aus der Natur des Tests. Denn was ist ein Test eigentlich? Er ist im Grunde ein empirischer Beweis. Wir stellen eine Hypothese auf und überprüfen diese in einem Experiment. Und in Analogie zu physikalischen Experimenten gilt auch für Softwaretests, dass je mehr ich mich dem Testobjekt nähere, das Ergebnis des Tests dadurch beeinflusst werden kann. Black-Box-Tests werden auf eigenen Testumgebungen durchgeführt, die einen ähnlichen Aufbau wie die Produktionsumgebung aufweisen sollten. Trotzdem bleibt es „ein Versuchsaufbau“. Es werden Mocks für fehlende Komponenten eingesetzt und der Log-Level erhöht, um mehr Informationen zu erhalten.

Grey-Box-Tests, also codenahe Tests, bei denen die zu testende Software ganz oder teilweise ausgeführt wird, sind nicht nur sehr nahe am Testobjekt. Mit Werkzeugen wie JUnit oder TestFX erweitern wir die Codebasis um neue Bestandteile. Es werden neue Zeilen Testcode geschrieben und Testframeworks als Library in die Softwarelösung eingebunden.

Aber auch bei Softwarelösungen wie QF-Test, Expecco oder Squish, die automatisierte Oberflächentests durchführen, rücken wir sehr nahe an das zu testende Objekt heran. Bei älteren Versionen der Automatisierungstools für graphische Oberflächen wurden die Aufnahme der Informationen dadurch erreicht, dass die Positionsdaten des GUI-Elements, wie zum Beispiel eines Buttons, gespeichert und zur Ausführungszeit ein entsprechendes Event abgesetzt wird. Anschließend erstellt die Software ein Screenshot und vergleicht jenes mit einem zuvor erstellten, um die Testergebnisse zu verifizieren. Also weitestgehend ungefährlich. Moderne Tools hingegen verfolgen einen anderen Weg. Sie verbinden sich über eine eigene „Engine“ mit der zu testende Applikation. Dadurch sind Sie in der Lage alle Control-Elemente der Oberfläche zu erfassen, deren Eigenschaften auszulesen und diese auch fernzusteuern. Die zugehörigen Daten werden als ein Modell der Applikation in so genannten GUI Maps abgelegt und sind die Grundlage für die anschließende Erstellung von Testskripten.

Die Auswirkung dieser Nähe zur zu testenden Software kann sein, dass bestimmte Fehlerwirkungen erst dadurch erzeugt oder, noch schlimmer, dadurch verschleiert werden bzw. nicht auftreten. Wir ändern die Grundlage des Tests durch den „komplizierten“ Testaufbau und können uns nicht sicher sein, dass die zu testende Software wirklich so reagiert hätte, wenn wir „nur“ manuell geprüft hätten.

Darum ist es wichtig, das Werkzeug und dessen Besonderheiten zu kennen sowie ein Bewusstsein für mögliche Fehlermaskierung durch die Codenähe der Tests zu haben. Wenn wir darin ein Risiko erkennen, sollten wir unsere automatisierten Tests durch andere manuelle Testarten ergänzen.

Aus dem Leben eines Testers

Während des Projektalltags stellt man sich manchmal die Frage, was mache ich eigentlich hier bzw. wissen die anderen im Team was ich tatsächlich tue? Als Tester habe ich mir diese Frage auch schon gestellt und einige Gedanken zusammengefasst. Daher findet man im Weiteren ein paar Ausschnitte aus meinem Alltag als Tester.

Daily

Wieder ist Daily und ich frage mich als Tester wie ich denn heute die Spezifikation von Testfällen attraktiv als getane, jetzige sowie zukünftige Arbeit verkaufen kann. Im Grunde vollzieht sich das ganze meist mit den Worten “Habe Testfälle für User Story xyz spezifiziert und mache damit weiter.”  Etwas eintönig und meist etwas belächelt, aber nun mal die Hauptaufgabe in den ersten Tagen eines Sprints. Schließlich setze ich als Tester doch den Grundstein aktuelle User Stories ordentlich zu testen.

Spannender wird es dann schon, wenn ich mitteile, dass ich nun auch Testfälle durchführe und voller Stolz den ein oder anderen Fehler verifiziert habe. Wobei von Stolz nicht die Rede sein kann. Kommt halt auf die Entwickler, die aktuelle Stimmung im Team, die Priorität des Fehlers oder der Selbstbewusstseinswahrnehmung des Testers (mir) an. Also kann es auch vorkommen, dass vor mich gemurmelt das Wort “Bug” fällt und schnell das Wort an andere übergeben wird. Warum eigentlich diese Zurückhaltung?

Ich als Tester habe die Verantwortung darauf aufmerksam zu machen, wenn etwas in der Software nicht so funktioniert wie definiert. Und das ist auch gut so. Denn wie will man qualitative Software liefern, wenn Fehler nicht akzeptiert sind und zu Stresssituationen oder Konflikten führen. Also nur Mut – der Fehler verschwindet nicht, wenn man ihn nicht anspricht (ganz im Gegenteil, er wächst, umso später er gefixt wird) und schnell ist er auch einmal im Wust der täglichen Entwicklungsarbeit in Vergessenheit geraten, wenn er nur in schriftlicher Form am Taskboard zwischen den großen User Storys hängt.

Regressionstests/Testautomatisierung

Apropos Taskboard – dies ist ein gutes Hilfsmittel die User Storys mit darin enthaltenen Aufgaben und deren Fortschritt im aktuellen Sprint im Auge zu behalten. Wenn man sich die Zeit nimmt, um innezuhalten und die Arbeit im Team mit Hilfe des Taskboards über Wochen oder auch Monate hinweg zu betrachten, könnte man zu folgender Behauptung gelangen: Die Entwickler arbeiten mit glänzenden, neuen Sachen und die Tester wühlen im Dreck der Vergangenheit mit Sicht auf den Glanz des Neuen. Dies bedeutet nicht, dass mir als Tester nicht bewusst wäre, dass Entwickler auch an bestehendem Code Anpassungen vornehmen müssen, und auch mal Bugs fixen. Aber ich als Tester habe eine ganz andere Sicht. Trotz all der automatisierten Tests, die unsere Entwickler schreiben, muss ich den Überblick darüber behalten was alles von Änderungen betroffen ist – ein kontinuierliches Zurückblicken auf Altlasten, während der Programmierer voranstürmt.

Damit sind wir dann auch bei der größten Herausforderung meines Alltags – Regressionstest. Den kann man zwar auch automatisieren, leider sind die Tools dafür aber nicht immer sehr freundlich zu mir. Werden sie nicht von Beginn an eingesetzt, bin ich kontinuierlich damit beschäftigt hinter den Änderungen der Entwickler her zu rennen. Aber selbst wenn ich sie gleich von Anfang an einsetze muss ich sie, um meine eigenen Aufgaben zu erfüllen, auf UI Ebene einsetzen und das ist langwierig und dummerweise eben selbst auch fehleranfällig. Dazu folgende Gedanken:

Testautomatisierungs-Tools suggerieren mir, dass ich durch einfaches Aufzeichnen von Testschritten Testautomatisierung machen kann. Leider wird mir nach anfänglichem Enthusiasmus klar, dass es damit nicht getan ist, da meine Testaufzeichnungen meist keinen Tag überlebt haben. Also auf zu neuen Ufern – diesmal programmieren und Aufzeichnungs-Tools verbannen. Da tauchen auch schon die nächsten Hindernisse auf. Denn ich bin kein guter Programmierer und muss mich nun mit kryptischen Sachen beschäftigen. Doch schon wird die nächste Idee geboren: Die Erfahrung der Entwickler zu Nutze machen. Auch da werden Grenzen gesetzt, denn das geht meist nur so lange gut, wie der Entwickler Zeit dafür hat bzw. gewillt ist, dies zu machen. Verständlich, denn der Entwickler will ja neue Sachen schaffen.

Ich stecke also in einem Zwiespalt: Schreibe ich automatisierte Tests oder mache ich alles manuell. Regressionstest sollte ich auf alle Fälle einplanen. Wie diese nun aussehen – automatisiert, manuell oder explorativ – kommt auf die verschiedensten Rahmenbedingungen an. Für mich ist Testfallautomatisierung jedenfalls kein Allheilmittel. Ich sehe den Mehrwert automatisierter Testfälle, die zu jedem Sprint ausgeführt werden können – größerer Testabdeckung, weniger manuelles Testen von vorgegebenen Workflows. Aber eine reine Testfallautomatisierung ist kein Allheilmittel, denn dies wird meine Testererfahrung und das damit verbundene Verfahren “Über-den-Tellerrand-Hinausblicken” nicht ersetzen.

Fazit

Auf alle Fälle sollte das Testen an sich – egal ob manuelles Testen, Regressionstests oder Testautomatisierung – im Team anerkannt sein und zusammen an der Qualitätssicherung gearbeitet werden. Denn schnell fühlt sich der Tester nicht mehr als Teil des Teams sondern Fremdkörper, wenn seine Arbeit nicht ernst genommen wird.