In heutigen Softwareprojekten sind GUI-Tests häufig vertreten. Diese dienen, wie alle Tests, dazu die Softwarequaliät aufrecht zu erhalten und somit die Geschwindigkeit in der Entwicklung möglichst linear zu halten. Doch diese Software befindet sich in der Entwicklung und ist somit Gegenstand konstanter Veränderung. Insbesondere verändert sich dabei auch die GUI mit ihren Komponenten. Mit diesen Änderungen an den Komponenten müssen die GUI-Tests umgehen können. Andernfalls schlagen sie fehl, sie zerbrechen. Ein häufiger Grund dafür ist, dass geänderte Komponenten von dem eingesetzten Framework für GUI-Tests nicht mehr gefunden und wiedererkannt werden. In dieser Seminararbeit sollen anhand einer Fallstudie einzelne Klassen an Fehlern in GUI-Tests gefunden werden. Ziel ist es diese zu vermeiden und somit den Wartungsaufwand für die GUI-Tests möglichst gering zu halten. Dabei werden eine Menge an Testfällen für die Version v2.00 von KeePass erstellt. Die nachfolgende Entwicklung wird simuliert, indem die Tests auf die nächste Version, also v2.01, angewendet werden. So lässt sich feststellen, ab wann die Tests fehlschlagen. Diese werden dann in Klassen gruppiert. Zusammengefasst lässt sich sagen, dass sich durch die Berücksichtigung von Persistenz in der Testumgebung, Trivialen Umbenennungen und Eigenschaften des GUI-Test Frameworks die überwiegende Mehrheit der Fehler vermeiden lässt.
Ähnlich zu Dimensionen an denen sich verschiedene Testarten ableiten lassen lassen sich auch verschiedene Dimensionen definieren durch die sich das SUT verändert. Beispiele dafür sind die Version, die Sprache oder die Platform. In dieser Seminararbeit sollen nur entstandene Änderungen durch die Entwicklung, also Version, betrachtet werden. Ziel dieser Studie ist es Fehler in GUI-Tests und Möglichkeiten diese zu vermeiden zu finden. Somit steigt die Qualität der GUI-Tests bei der initialen Erstellung und diese zerbrechen später weniger häufig. Es soll also mit einem zusätzlichen Zeiteinsatz bei der Erstellung die Qualität gesteigert werden, um im späteren Verlauf häufiges Anpassen der GUI-Tests zu vermeiden. Ist dabei die zusätzlich eingesetzte Zeit zu Beginn geringer als die Summe im späteren Verlauf potentiell aufgewendeten Zeit zur Anpassung ist der Wartungsaufwand gesunken. Dies ist in allen Fällen wünschenswert.
Die erste Gruppe an Fehlern wurde durch Persistenz in der Testumgebung verursacht. Dies bedeutet, dass über die Ausführung von Tests hinweg vom SUT Daten persistent geschrieben und genutzt werden.
Im Fall von KeePass war dies im beispielsweise Dialog "Einstellungen" vorhanden. Ab Version 2.07 speichert KeePass den geöffneten Tab beim Schließen des Dialoges. Beim nächsten Öffnen des Dialoges ist der gespeicherte Tab vorausgewählt und nicht der erste Tab wie in den Version 2.00 bis 2.06. Der Tests waren unter der Annahme, dass immer der erste Tab ausgewählt ist geschrieben. Sie schlugen somit ab v2.07 fehl.
Insgesamt sind zwei der 17 fehlgeschlagenen Tests durch diesen oder einen anderen Grund fehlgeschlagen. Dieser Fehler ist sehr leicht zu vermeiden, indem die persistenten Daten vor der Ausführung der Tests gelöscht werden. Bei einem selber entwickelten SUT ist auch eine Funktion denkbar bei der das SUT durch ein Argument einen sogenannten clean start ausführt. Also ohne Berücksichtigung der persistenten Daten.
Die in dieser Fallstudie ermittelte größte Gruppe an Fehler bilden triviale Umbenennungen. Dies sind Umbenennungen, die einem normalen Nutzer möglicherweise nicht auffallen jedoch bei automatisierten GUI-Tests aufgedeckt werden. Beispiele aus KeePass dafür sind Umbenenungen von Find zu Find..., von Side-By-Side zu Side by Side oder von Lock Windows zu Lock Window or Logout.
Mit zehn von 17 fehlgeschlagenen Tests aus diesem oder einem anderen Grund ist diese Gruppe die Größte der hier aufgeführten Gruppen. Es ist also von großen Interesse diese Fehler zu vermeiden.
Studie Möglichkeiten diese Fehler zu vermeiden sind breiter gefächert als bei der ersten Gruppe. Beispielsweise können durch Tests ohne Case Sensitivity diese Fehler vermieden werden. Falls eine Komponente bereits durch einen Substring ausreichend charakterisiert ist, kann lediglich auf diesen Substring gematcht werden. Ein anderer Fall, in dem eine gewisse Fehlertolernz zugelassen werden soll, könnten diese Toleranz durch eine Levenshtein Distanz realisiert werden. So können die Komponenten im Rahmen dieser Toleranz umbenannt werden ohne dass die GUITests zerbrechen. Ermöglicht das GUI-Test Framework den Einsatz von Regulären Ausdrücken können auch diese mit dem damit verbundenen Grad an Flexibilität eingesetzt werden.
Die letzte Gruppe an Fehlern lässt sich vermeiden, indem man die Eigenschaften des GUI-Test Frameworks kennt. In dieser Fallstudie also QF-Test und die Eigenschaften bei der Wiedererkennung von Komponenten. Bei QF-Test handelt es sich um einen wahrscheinlichkeitsbasierten Ansatz. Anhand von bestimmten Eigenschaften wird für jede Komponente eine Wahrscheinlichkeit berechnet, dass es sich um die gesuchte Komponente handelt. Die Komponente mit dem höchsten Ergebnis wird schließlich ausgewählt. Dabei wird der eindeutige Name der Komponente, der beispielsweise mittels setName() gesetzt werden kann besonders stark gewichtet.
Wie in Abbildung 2.4 zu erkennen wurden in KeePass während der Entwicklung die Namen von Komponenten geändert. Sonstige Eigenschaften dieser Komponenten änderten sich hingegen nicht, wodurch diese Änderung optisch nicht zu erkennen ist. Jedoch sind die Tests mit QF-Test und der verwendeten Gewichtung fehlgeschlagen. Insgesamt sind sechs der 17 fehlgeschlagenen Tests durch geänderte Namen oder einen anderen Grund fehlgeschlagen. Auch diese Fehler lassen sich leicht vermeiden, indem die Namen der Komponenten zu Beginn konsistent gesetzt werden.
Das Ergebnis der Fallstudie ist insgesamt deutlich. So sind 14 der 17 fehlgeschlagenen Tests durch mindestens einen der drei Fehler gescheitert. Lediglich die restlichen drei fehlgeschlagenen Tests liegen außerhalb dieser Fehlerklassen. Natürlich können diese Ergebnisse nicht ohne Einschränkungen auf jedes beliebige Softwareprojekt übertragen werden. Die hier gezeigten Klassen an Fehler sind sehr spezifisch und gelten im Gesamten nur für die Bedingungen der Fallstudie. Inwiefern die Ergebnisse auf andere Softwareprojekte übertragen lassen ist möglicher Gegenstand anderer Arbeiten. Mögliche Änderungen an den Bedingungen umfassen beispielsweise das verwendete GUI-Test Framework, das SUT, die Versionen, die Tests und Testcases, das verwendete Betriebssystem und viele weitere.
Jedoch hat sich deutlich gezeigt, dass durch wenige Fehler in den GUI-Tests ein großer Anteil dieser zerbricht. Es lässt sich also die Robustheit von automatisierten GUI-Tests erhöhen, indem Fehler innerhalb der ermittelten Fehlerklassen vermieden werden. Als direkte Folge davon sinkt der Wartungsaufwand für die GUI-Tests, was in jedem Fall wünschenswert ist.
Die komplette Seminararbeit können Sie hier (PDF) lesen.
Seminararbeit: Warum zerbrechen meine automatisierten GUI-Tests? Juli 2020 - Leonard Husmann, Fakultät für Informatik der Technischen Universität München, Deutschland.