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.