Automatisierung des Tests von Java-Swing-GUIs

Transcription

Automatisierung des Tests von Java-Swing-GUIs
Automatisierung des Tests
von
Java-Swing-GUIs
Ausarbeitung Aktuelle Themen der Informatik
Prof. Dr. Friedbert Kaspar
HFU - Hochschule Furtwangen University
Robert-Gerwig-Platz 1
78120 Furtwangen
Dominik Jall
Fakultät Computer Networking (CN 7)
Matrikel Nr. 216385
E-Mail: dominik.jall@web.de
Pflichtveranstaltung CN 8
Sommersemester 2006
1
Inhaltsverzeichnis
Vorwort..........................................................................................................................3
Einleitung.......................................................................................................................4
Warum GUIs automatisiert testen?................................................................................5
Werkzeuge und Methoden.............................................................................................7
QftestJUI........................................................................................................................9
Andere Ansätze............................................................................................................11
Fazit.............................................................................................................................13
Quellen.........................................................................................................................14
2
Vorwort
„Ein weitverbreiteter Fehler, den Menschen begehen, wenn sie
etwas vollkommen Narrensicheres entwickeln, ist den Einfallsreichtum vollkommener Narren zu unterschätzen.“
Douglas Adams
3
Einleitung
„Softwaresysteme werden durch den Anwender heute meist über grafische Benutzerschnittstellen (GUI, Graphical User Interface) gesteuert.
Aufgrund der vielfältigen Anwenderinteraktionen und der grafischen
Kontrollelemente in der GUI sind wohldefinierte Testszenarien komplex
und daher schwer umzusetzen. Solche Tests sind zeitraubend und kostenaufwändig. Kein Entwickler ist zudem erfreut, wenn er alle Interaktionen manuell austesten und dokumentieren muss, da solche Tests
nicht nur monoton, sondern auch entsprechend arbeitsintensiv sind.
Abhilfe schaffen hier Werkzeuge, die solche Szenarien automatisieren,
so genannte GUI Capture & Replay-Werkzeuge.“ [1]
Mittlerweile hat sich durch die zunehmende Anwendung von Methoden aus den Ingenieurwissenschaften das ständige Testen von Software auch bereits während des Entwicklungsprozesses
verbreitet. Nicht zuletzt durch moderne Ansätze wie „Extreme Programming“ [2] oder
„Testgetriebene Programmierung“ [3] und den andererseits ständig an Komplexität zunehmenden
Softwareprojekten
spielt
das Testen
von
Software
heutzutage
eine
große
Rolle
im
Entwicklungsprozess.
Dennoch spielt derzeit das intensive Testen von GUIs, also den grafischen Benutzeroberflächen eine
eher untergeordnete Rolle, vielmehr konzentrieren sich die Testszenarien eher auf Programmlogik,
Datenintegrität und Threadsicherheit. Das liegt zum einen daran, dass GUIs in Projektgruppen oft
eher als weniger wichtig angesehen werden, schließlich werden sie nicht zur Abhandlung der
Algorithmen und Kernprozesse eines Programms benötigt, sie könnten genauso gut durch einfache
Funktionsaufrufe mit entsprechenden Parametern ersetzt werden, den nichts anderes vollführen sie
„unter der Haube“: Der Benuter klickt auf einen Knopf, der Klick löst den Aufruf einer bestimmten
Methode auf, die die Geschäftslogik dahinter implementiert. Da GUIs oft icht von den Entwicklern
der
Logik
sondern
von
Designern
erstellt
werden
herrscht
hier
naturgemäß
ein
Kommunikationsproblem vor, man ist sich „Art-fremd“. Auf der anderen Seite bestehen neben
diesen, eher psychologischen, Problemen handfeste Probleme bei der Implementierung von GUITests. Da eine GUI ein interaktives Medium ist, dass Eingaben eines Benutzers benötigt, um seinen
Sinn und seine Aufgabe zu erfüllen, andererseits aber kein fest vorgegebener Ablauf in der
Bedienung vorgegeben sein muss, steht der Entwickler von Testfällen hier vor einer komplexen
Aufgabe, die viel Wissen, sowohl um Programmierung als auch um „den Benutzer“ erfordert.
4
Warum GUIs automatisiert testen?
Nach den oben erwähnten Problemen bei der Ausweitung von Tests auch auf grafische
Benutzeroberflächen, bei gleichzeitig scheinbar geringem Nutzen für die Software, warum sollten
Firmen dennoch das GUI-Testing, insbesondere die Automatisierung des Testings in Betracht
ziehen?
Zum einen wird durch GUI-Testing die Testabdeckung des Softwaresystems erhöht. Es kann danach
nicht nur von getesteter Logik, Datenbankzugriffen und Integrität ausgegangen werden, sondern
auch von einer stabilen GUI, die garantiert das tut was sie soll. Andererseits kann die Sicherheit des
gesamten Programms erhöht werden, indem „Schlupflöcher“ (z.B: in Anmeldedialogen) verhindert
werden. Zu guter Letzt, ein nicht unerheblicher Faktor, kann die GUI bereits „vorgetestet“ werden,
bevor der erste menschliche Tester sie zu Gesicht bekommt. So können die gröbsten Design oder
Implementierungsprobleme im Vorfeld zeit- und kostensparend ausgemerzt werden.
Dennoch: Dies alles könnte auch intern durch menschliche „Vortester“ bewerkstelligt werden –
warum also automatisiert testen?
Ich schreibe diese Ausarbeitung aus der Sicht der Anwendungsentwickler. Ich habe bereits einige
kleinere und größere GUIs für diverse Projekte entworfen und getestet und ich denke ich spreche
für einen Großteil der Entwicklergemeinde, wenn ich behaupte, dass dies kein besonders kreativer
oder motivierender Teil der Arbeit ist. GUIs zu testen kostet Zeit, Nerven und erzeugt ausserdem
eine Menge schlecht zu lesenden Code (insbesondere bei der Verwendung sog. „GUI-Editoren“, wie
etwa [4]
oder [5]). Andererseits kann wohl kein Mensch alle Schwachstellen und
„Bedienungs(un)arten“ einer GUI testen, geschweige denn fielen sie ihm alle ein (siehe Vorwort).
Das Entwerfen von Testfällen für GUIs ist also nicht nur zeitaufwändig und erfordert viel
„negativer Kreativität“ („was kann ich alles falsch machen?“), viel schlimmer noch: Am Ende
dieses aufreibenden Vorgangs kann sich der Entwickler nicht mal sicher sein, dass seine GUI jetzt
hundertprozentig getestet ist. Letztlich muss beim Testen der GUI, wie bei jedem anderen Test auch
immer nur ein kleiner Teil des Systems verändert werden, beispielsweise ein Textfeld enthält einen
anderen Wert oder eine Checkbox wird aktiviert. Nach jeder Veränderung muss erneut getestetet
werden, um festzustellen, wo genau ein Fehler liegt, ähnlich wie bei einem wissenschaftlichen
Experiment. Beim Testen von Code kann hier der Monotonie durch geschickt programmierte
Schleifen oder rekursive Aufrufe abgeholfen werden, die Datenstrukturen mit immer anderen
Werten füllen. Beim GUI-Test aber müsste stetig ein Knopf gedrückt oder ein Regler verschoben,
dann das Programm neu geladen und wieder etwas verändert werden. Dass hierbei keine Freude
aufkommt muss wohl niemanden wundern.
5
All diese Nachteile manueller Tests machen in professionellen Umgebungen, die oft sehr GUIintensive Software entwickeln die Automatisierung von GUI-Tests zu einem Muss. Weitere Gründe
sind:
•
Reduktion des manuellen Aufwands
•
Reduktion der Testkosten
•
Reproduzierbarkeit
•
Qualitätsverbesserung
[1]
6
Werkzeuge und Methoden: Capture & Replay
Welche Möglichkeiten bietet der Markt zum automatisierten Testen von Benutzeroberflächen?
In dieser Ausarbeitung möchte ich näher auf die sog. „Capture & Replay“ Tools eingehen.
Dabei handelt es sich, vereinfacht gesagt, um Softwarewerkzeuge, die dynamisch GUIs laden
können und (je nach Ausprägung) einige bis sämtliche Interkaktionen, die der Nutzer mit der GUI
machen kann aufzeichnen und zu einem späteren Zeitpunkt wieder „abspielen“ können. Dabei
können an definierten Punkten sog. „Checks“ eingebaut werden, die zu diesem Zeitpunkt bestimmte
Zustände der GUI überprüfen und folgende Zustände einnehmen können:
•
Check OK – Der Zustand ist wie erwartet.
•
Check Exception – Der Zustand liefert einen erwarteten Fehler, es ist also der Check
fehlgeschlagen, weil die GUI nicht den gewünschten Wert liefert.
•
Check Error – Der Zustand ist unerwartet fehlerhaft. Nicht der „gewünschte Fehler“ trat ein,
sondern ein anderer, nicht geplanter Zustand trat ein.
Die „Replay“ Funktion der Tools agiert dabei wie ein „echter“ Benutzer, sie simuliert also
Mausklicks oder Tastatureingaben ganz so, als würde ein Mensch vor dem Programm sitzen, nur
eben viel schneller und präziser. In meinem Fall, also dem Testen von Swing-GUIs bietet Java von
Haus aus eine Schnittstelle, mit der bequem Eingaben des Benutzers simuliert werden können,
nämlich die Klasse java.awt.robot. [6] Um diese Klasse, sowie um das Junit-Framework [12] sind
bisher eine ganze Reihe brauchbarer Werkzeuge entstanden, von denen ich hier besonders auf das
QftestJUI der Firma QualityFirst [7] eingehen möchte, da hier die Bedienung besonders intuitiv und
anschaulich ist. Aber auch die anderen (meist Opensource-) Werkzeuge sollen im Abschnitt
„Andere Ansätze“ Erwähnung finden. Die weiteren grundlegenden Anforderungen an C&RWerkzeuge sind:
•
Capture Mode
•
Programming Mode
•
Checkpoints und
•
Replay Mode
Neben den bereits erläuterten Modi existiert noch der „Programming Mode“, mit dem es möglich
sein soll, auch komplexe Testszenarien zu implementieren, als nur das simple „Abspielen“ von
Tests.
7
Folgende Eigenschaften zeichnen das Tool von QFS aus:
•
GUI-basiert, daher intuitiv zu bedienen
•
Kommerziell
•
Kann Reports in HTML generieren, was eine weitere Verarbeitung der Reports vereinfacht
•
Registriert sämtliche Reaktionen der Anwendung auf die simulierten Aktionen (Exceptions etc.)
•
Kostenlose Evaluierungsversion, was insbesondere den Entscheidungsträgern in einem
Softwareprojekt hilft, die Nutzen mit den eventuellen Kosten des Tests abzuwägen.
Da es sich um kommerzielle Software handelt sollten vor der Einführung des Werkzeugs unbedingt
noch offene Fragen geklärt werden, damit hinterher nicht die Kosten den Nutzen überwiegen:
•
Verursacht die Automatisierung höhere Kosten als der manuelle
Test? Wie viel mehr?
•
Automatisierte Tests haben eine begrenzte Lebensdauer. Wie lange
wird das Testszenario gültig sein?
•
Während der Gültigkeit des Testszenarios können weitere Fehler
entdeckt werden, die in vorangegangenen Durchläufen nicht auftauchten. Wie groß ist dieser Nutzen gegenüber den Mehrkosten
der Automatisierung? [1]
Können diese Fragen zugunsten einer Automatisierung des Testprozesses beantwortet werden, steht
einer breiteren Einführung des Werkzeugs mit den damit verbundenen Änderungen im
Entwicklungsprozess nichts mehr im Wege. Es sei jedoch gesagt, dass sich die automatisierte
Herangehensweise nicht immer lohnt. Dazu sollte die GUI der Software bereits einigen Umfang
sowie eine höhere Komplexität haben. Ein Anmeldedialog oder ein einfaches Fenster ohne weitere
zusätzliche Interaktionsmöglichkeiten kann als zu gering erachtet werden, als dass sich der
Aufwand der Automatisierung lohnen würde. In einem solchen Fall würde ich eher den Einsatz
einer kostenlosen OpenSource-Alternative empfehlen wie z.B. jfcUnit [8] oder Marathon [9]
8
QFtestJUI
Abbildung 1 zeigt einen Screenshot des Hauptfensters des Programms.
Abbildung 1: qftestJUI
Zur Erläuterung:
In der Mitte des Fensters auf der linken Seite ist eine Baumstruktur der gesamten Testsuite zu sehen.
Dabei werden sowohl die eigentlichen Tests, wie auch die abzuspielenden Sequenzen (Test) oder
zusätzliche Konfigurationseinstellungen, die nicht direkt etwas mit dem eigentlichen Testen zu tun
haben dargestellt. Dazu gehören etwa Einstellungen zur JVM, die benötigt werden, um die zu
testenden GUI-Klassen erst zu laden. (Extrasequenzen). Auf der rechten Seite wird der Inhalt der
linken Seite zur Bearbeitung dargestellt. Im Bild kann man sehen, dass hier benötigte Dateien für
die Testsuite, also Includefiles, andere Abhängigkeiten, Variablen wie z.B. Classpath etc. gesetzt
werden können. Ist die GUI einmal geladen, kann im Abschnitt „Fenster und Komponenten“ eine
hierarchische Baumdarstellung der Oberfläche gefunden werden. Sie dient mehr der Übersicht über
komplexere GUIs. Der grüne „Play“-Knopf startet die GUI, bzw. das Abspielen von
9
aufgezeichneten Sequenzen oder Tests. Der grüne Haken wird benutzt, um in den „Check-Modus“
zu schalten. Es können dann bei laufender GUI einzelne Checks für Komponenten festgelegt
werden. Der rote „Recording“-Knopf wird benutzt, um Sequenzen des virtuellen Benutzers
aufzuzeichnen, der später anstelle eines echten Testers die Knöpfe und Schalter des Programms
betätigt. Zusammen mit den Checks läuft somit eine komplett automatische Testreihe der GUI ab,
Die am Ende im Menü „Wiedergabe“->“Protokoll“ nachverfolgt werden kann. Dort finden sich u.a.
ein Report über alle Warnungen und Fehler, die während des Tests auftraten, zusammen mit einem
Zeitstempel und einem Screenshot der GUI zum Zeitpunkt des Fehlers.
Die Knöpfe auf der rechten oberen Seite haben die übliche Bedeutung beim Debugging: Step into,
Step over, Step out, etc. nur eben in diesem Fall nicht für einzelne Codezeilen, sondern für
Testabschnitte, bzw. aufgezeichnete Sequenzen. So muss z.B. nicht jedes Mal der gesamte Test
durchlaufen werden, wenn nur in einem bestimmten Bereich etwas nicht erwartungsgemäß abläuft.
Dies ist sehr hilfreich, da GUI-Tests, wie Softwaretests allgemein, teilweise sehr umfangreich und
langwierig sein können und bis zu mehreren Stunden Zeit benötigen.
Jede einzelne Sequenz kann hierbei in einem Eigenschaftsfeld modifiziert werden. Testsuites und
Protokolle werden als XML-Dateien gespeichert, d. h. als normaler Text in wohldefinierter Syntax.
Zum Suchen und Ersetzen und bei der Überprüfung von Daten, die an der Oberfläche angezeigt
werden, können reguläre Ausdrücke verwendet werden. Anstelle der fest verdrahteten Texteingaben
für Eigenschaftswerte können auch variable Werte verwendet und die aufgenommene Sequenz in
eine Prozedur umgewandelt werden. Auf diesem Weg lassen sich schnell datengetriebene Tests
erstellen, die immer wieder dieselbe Sequenz durchlaufen, aber jedes mal mit anderen Daten. Diese
können z. B. aus einer Datei oder einer Datenbank gelesen werden. Aktionen, die der Anwender
ausführt, werden von der Java VM in Events umgewandelt. Jeder Event hat eine Zielkomponente.
Für einen Mausklick ist das die Komponente unter dem Mauszeiger, für einen Tastendruck die
Komponente, die den Tastaturfokus (keyboard focus) besitzt. Wenn qftestJUI einen Event
aufzeichnet, nimmt es zusätzlich Informationen über die Zielkomponente mit auf, sodass die
Komponente später beim Abspielen des Events wieder lokalisiert werden kann, selbst wenn sich
einige Parameter wie Größe oder Lokation geändert haben. Dies ist insbesondere dann Hilfreich,
wenn Regressionstests mit komplexen Anwendungen durchlaufen werdens sollen, deren Testfälle
ständig auch bei veränderten GUIs durchlaufen werden müssen, ohne dass das Testprogramm aus
dem Tritt kommt.
10
Andere Ansätze
Neben qftestJUI finden sich derzeit noch einige Alternativen, die aber allesamt den Nachteil einer
schlechteren Bedienbarkeit mangels GUI haben. Dennoch stehen die meisten dem kommerziellen
Tool in nichts nach und professionelle Programmierer, die bereits Erfahrungen mit Junit gesammelt
haben dürften mit der Integration in das eigene Projekt keine Schwierigkeiten haben.
Marathon [9]
Marathon erfasst semantische Aktionen, die auf Komponenten ausgeführt werden, anstatt sich auf
Tastatur und Mausevents zu konzentrieren. Marathon besteht aus einem Recorder, einer Ablauflogik
und einem Editor. Die Testskripts sind in Python aufgebaut. [1] Der Editor von Marathon bietet eine
rudimentäre GUI, mit der die wichtigsten Einstellungen gemacht werden können, ist jedoch
keinesfalls als ähnlich ausgereift wie der von qftestJUI zu bewerten. Der Vorteil liegt in der
semantischen, also sinnhaften Erfassung der Aktionen. Dadurch bietet Marathon eine größere
Flexibilität als reine Keyboard- oder Mauslogger.
Pounder [10]
Pounder ermöglicht dynamisches Laden von GUIs, die Aufzeichnung von Skripten und deren
Wiederverwendung in Testframeworks wie JUnit. Pounder unterliegt der GNU Library General
Public License (LGPL) [11] und ist somit frei verfügbar. [1] Pounder verfügt ebenso wie Marathon
über eine rudimentäre GUI, welche Swing-basiert ist und kann Testfälle und -suites für Junit
erzeugen. Mittlerweile wird das Projekt jedoch nicht mehr aktiv weiterentwickelt, die Homepage
verweist auf andere Tools, unter anderem auf Marathon und jfcUnit.
JcfUnit [8]
jfcUnit ist eine Erweiterung des JUnit Frameworks, die es ermöglicht Unit-Tests mit SwingKomponenten zu verbinden. jfcUnit verwendet XML zur Aufzeichnung seiner Tests. [1] Dem
Entwickler, der ständig schon durch den herkömmlichen Testprozess seiner Software mit Junit zu
tun hat wird die Integration von jfcUnit leicht fallen, da es sich dabei schlicht um eine um SwingKomponenten erweiterte Junit-Version handelt. JfcUnit hilft dabei den Entwicklern, Testfälle für
Swing-basierte Applikationen zu schreiben und unterstützt:
•
Das Mitschneiden von Fensterhandles und Ids von Komponenten, die durch den Javacode des
Projekts erzeugt wurden.
•
Das Auffinden von Komponenten innerhalb einer Objekthierarchie der darüber liegenden
Container.
11
•
Eventraising auf den gefundenen Komponenten, also Aktionen wie Klick auf Knöpfe,
Texteingaben etc.
•
Thread-sicheres Handlich von Tests (Checks) auf Komponenten.
Neben den erwähnten findet sich noch eine Vielzahl kleinerer Projekte im Netz, es handelt sich bei
den vorgestellten Tools lediglich um eine kleine Auswahl. Dennoch bleibt zu sagen, dass die
meisten kleineren, und meist quelloffenen Tools sich nur zum Test kleinerer Softwareprojekte
eignen und für größere und komplexere Anwendungen die Wahl eines teureren, proprietären
Werkzeugs mit Support vom Hersteller auf jeden Fall bedacht werden sollte.
12
Fazit
In dieser Ausarbeitung habe ich anhand eines professionellen Werkzeugs und kleinerer, freier Tools
das Thema „Automatisiertes Testen von Swing-GUIs“ erläutert. Es sei gesagt, dass sich das Thema
„Testing“ immer mehr in den Vordergrund aktueller Softwareprojekte schiebt und sich so zu einem
zentralen Punkt des Softwareengineering entwickeln wird. Nur durch ständiges Absichern und
Testen kann bei der Komplexität heutiger Großprojekte noch die Sicherheit und Qualität
gewährleistet werden. Menschen machen natürlich Fehler und die werden sie wohl immer machen,
aber durch die Unterstützung einer Software kann bereits heute ein Großteil der gröbsten Fehler im
Design und in der Implementierung von Komponenten verhindert werden. Nicht zuletzt durch den
ständig ansteigenden Anteil an zugekauften Features, die nicht im eigenen Haus entwickelt wurden
(„Make or Buy“) muss sich das obligatorische Testen von GUIs im gesamten Bereich der
Komponentenentwicklung durchsetzen, da sonst auf lange Sicht die Qualität der Software
insgesamt leidet. Für das Testen in komplexen Applikationsentwicklungen ist es unabdingbar, die
grafischen Nutzerschnittstellen zu erproben. Dies sollte sowohl in einem Akzeptanztest der
zukünftigen Anwender als auch in einem funktionalen Test innerhalb der Systemlogik geschehen.
Für diesen Zweck werden diverse CR-Werkzeuge zur Verfügung gestellt, und im Hinblick auf
Kostenreduktion durch Testautomatisierung sind diese Toolinvestitionen durchaus gerechtfertigt.
Nichts desto trotz steht die Software, die diese Prozesse unterstützt noch relativ am Anfang und es
muss sich erst noch zeigen, was die „best practises“ der softwaregestützten Automatisierung von
GUIs in modernen Anwendungen sind.
13
Quellen
[1] Javaspektrum 6 / 2004, Titelthema
[2] „Extreme Programming“ - http://de.wikipedia.org/wiki/Extreme_Programming
[3] „Testdriven Development“ - http://de.wikipedia.org/wiki/Testgetriebene_Entwicklung
[4] VisualEditor - http://www.eclipse.org/vep/WebContent/main.php
[5] NetBeans - http://www.netbeans.org/
[6] java.awt.robot - http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Robot.html
[7] Quality First Software - http://www.qfs.de/
[8] jfcUnit http://jfcunit.sourceforge.net/
[9] Marathon - http://marathonman.sourceforge.net/
[10] Pounder - http://pounder.sourceforge.net
[11] GPL, LGPL - http://www.gnu.org/licenses/licenses.html
[12] Junit - http://www.junit.org/index.htm
14