Handbuch

5
Komponenten

Auch wenn man sie zunächst oft gar nicht bemerkt - zumindest bis die erste ComponentNotFoundException auftritt - sind die 'Komponenten' das Herz einer Testsuite. Alles andere dreht sich direkt oder indirekt um sie. Um das genauer zu erklären, müssen wir etwas weiter ausholen:

5.1
Hierarchie der Komponenten eines GUI

Die grafische Oberfläche (Graphical User Interface, kurz GUI) einer Applikation besteht aus einem oder mehreren Fenstern, die verschiedene Komponenten beinhalten. Diese Komponenten sind ineinander verschachtelt und bilden eine hierarchische Struktur. Komponenten, die andere Komponenten enthalten, heißen Container. Da QF-Test selbst eine komplexe Applikation mit grafischer Oberfläche ist, kann das Hauptfenster gut als Beispiel dienen:

Komponenten einer GUI
Abbildung 5.1:  Komponenten eines GUI

Das Fenster (window) enthält eine Menüleiste (menu bar), welche wiederum die Menüs (menu) für QF-Test enthält. Darunter befindet sich die Werkzeugleiste (toolbar) mit den Knöpfen (toolbar buttons). Der Hauptteil bedient sich einer split pane um die Baumansicht und die Detailansicht zu trennen. Die Baumansicht besteht aus einer Beschriftung (label) "Testsuite" und dem Baum (tree). Die Detailansicht enthält selbst wieder eine komplexe Hierarchie von verschiedenen Komponenten wie Textfeldern (text field), Knöpfen (button), einer Tabelle (table), etc. Dabei gibt es noch eine ganze Reihe von Komponenten, welche man nicht auf den ersten Blick erkennt. So steckt der Baum z.B. in einer scroll pane, die scroll bars anzeigt, wenn der Baum zu groß für seinen Bereich wird. Verschiedene panes dienen lediglich als Container und Hintergrund für andere Komponenten, z.B. der Bereich, der die "OK" und "Abbrechen" Knöpfe enthält.

SWT In SWT heißen die GUI Komponenten Control, Widget oder Item. Sofern nicht explizit anders angegeben bezieht sich der Begriff "Komponente" in diesem Handbuch auch auf diese SWT Elemente und nicht nur auf AWT/Swing Component Objekte.

JavaFX Analog verhält es sich für JavaFX Komponenten, die Node heißen und einen Scene graph bilden, der die Komponentenhierarchie bildet.

Windows Auch für die GUI Komponenten von nativen Windows Anwendungen, die als Controls bezeichnet werden, verwenden wir im Handbuch den Ausdruck Komponente.

Web Die interne Repräsentation einer HTML Seite basiert auf dem Document Object Model (DOM), welches vom W3C definiert wurde. Das DOM ist eine Baumstruktur aus verschiedenen Knoten. Der Wurzelknoten, ein Document kann Frame Knoten mit weiteren Document Knoten und/oder ein Wurzel-Element mit einer Baumstruktur aus weiteren Element Knoten enthalten. Obwohl eine HTML Seite mit ihrem DOM sich stark von einer Swing, JavaFX oder SWT Oberfläche unterscheidet, eignen sich die Abstraktionen von QF-Test in gleicher Weise. Der allgemeine Begriff "Komponente" findet daher auch für DOM Knoten Anwendung.

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 QF-Test einen Event aufzeichnet, nimmt es zusätzlich Informationen über die Zielkomponente mit auf, so dass der Event später wieder für die gleiche Komponente abgespielt werden kann.

Das mag trivial und offensichtlich klingen. Tatsächlich ist die Wiedererkennung der Komponenten aber einer der komplexesten Teile von QF-Test. Der Grund dafür liegt in der Notwendigkeit, mit einem gewissen Grad an Veränderungen zurechtzukommen. QF-Test ist als Werkzeug für die Durchführung von Regressionstests ausgelegt. Wird eine neue Version des SUT getestet, sollten bestehende Tests idealerweise unverändert durchlaufen. Folglich muss sich QF-Test an ein möglicherweise geändertes GUI anpassen können. Würden z.B. die "OK" und "Abbrechen" Knöpfe vom unteren Rand der Detailansicht nach oben verschoben, würde QF-Test Events für diese Knöpfe immer noch korrekt wiedergeben. Das Ausmaß an Änderungen, an die sich QF-Test anpassen kann, ist unterschiedlich und hängt nicht zuletzt von der Bereitschaft der Entwickler ab, vorauszudenken und ein klein wenig mitzuhelfen, das SUT möglichst gut für automatische Tests tauglich zu machen. Mehr dazu später in Abschnitt 5.6 und Abschnitt 5.7.

5.2
'Komponenten' in QF-Test

Die aufgezeichneten Komponenten wandelt QF-Test in 'Fenster' und 'Komponenten' Knoten um, deren hierarchische Anordnung der Struktur des GUI im SUT entspricht. Diese Knoten befinden sich unterhalb des 'Fenster und Komponenten' Knotens. Das folgende Bild zeigt einen Ausschnitt der 'Komponenten', die zum QF-Test Hauptfenster gehören:

Komponentenhierarchie eines Swing SUT
Abbildung 5.2:  Komponentenhierarchie eines Swing SUT

Web Das Wurzel-Document einer Webseite wird nicht durch einen 'Fenster' Knoten, sondern den speziellen Knoten 'Webseite' repräsentiert. Verschachtelte Document Knoten in Frames entsprechen 'Komponenten'.

Immer wenn eine Sequenz aufgezeichnet wird, werden neue Knoten für die Komponenten angelegt, die noch nicht in der Testsuite vorhanden sind. Wird die Sequenz später gelöscht, bleiben die 'Komponenten' erhalten, daher haben 'Komponenten' eine gewisse Tendenz sich anzusammeln. Das Popupmenü (rechte Maustaste) für 'Fenster' und 'Komponente' Knoten hat zwei Einträge namens »Ungenutzte Komponenten markieren...« und »Ungenutzte Komponenten entfernen«, die jene 'Komponenten' markieren oder ganz entfernen, auf die sich kein anderer Knoten in dieser Testsuite mehr bezieht. Vorsicht ist geboten, falls Sie Variablen in 'QF-Test ID der Komponente' Attributen verwenden, da die Automatik diese nicht erkennt. Werden 'Komponenten' aus anderen Testsuiten referenziert, sollte diese zum selben Projekt gehören oder das Attribut 'Abhängige Dateien (umgekehrte Includes)' des 'Testsuite' Wurzelknotens korrekt gesetzt sein.

Die Attribute von 'Komponenten' und der Algorithmus zur Wiedererkennung werden ausführlich in Abschnitt 43.2 beschrieben. In den folgenden Abschnitten werden wir uns auf den Zusammenhang zwischen 'Komponenten' und dem Rest der Testsuite konzentrieren.

Windows Für die Steuerung von nativen Windows-Anwendungen stehen einige Prozeduren im Package qfs.autowin der Standardbibliothek zur Verfügung. Die Kriterien zur Identifikation der Windows Komponenten müssen manuell mit den im Package qfs.autowin.helpers zur Verfügung gestellten Prozeduren ermittelt werden. Sie werden dann mittels Parameter an die Prozeduren übergeben, die Aktionen auf den Komponenten ausführen. Nähere Informationen hierzu finden Sie Kapitel 27.

5.3
'QF-Test IDs' von 'Komponenten'

Jeder Knoten einer Testsuite besitzt ein 'QF-Test ID' Attribut, welches für die meisten Knoten keine besondere Bedeutung hat und automatisch verwaltet wird. Für 'Komponenten' Knoten hat die 'QF-Test ID' dagegen eine wichtige Funktion. Andere Knoten mit einer Zielkomponente, wie Events oder Checks, haben das Attribut 'QF-Test ID der Komponente', welches sich auf die 'QF-Test ID' des 'Komponente' Knotens bezieht. Dieser indirekte Bezug ist sehr nützlich: wenn sich die Oberfläche des SUT auf eine Weise ändert, die QF-Test nicht automatisch kompensieren kann, müssen lediglich die 'Komponenten' Knoten der nicht erkannten Komponenten angepasst werden und der Test läuft wieder.

Es ist sehr wichtig sich klarzumachen, dass die 'QF-Test ID' einer 'Komponente' nur ein künstliches Konzept für den internen Gebrauch innerhalb von QF-Test ist, nicht zu verwechseln mit dem Attribut 'Name' welches zur Identifikation der Komponente im SUT dient, worauf wir im folgenden Abschnitt genau eingehen werden. Der eigentliche Wert der 'QF-Test ID' ist vollkommen irrelevant und steht in keinem Bezug zum GUI des SUT. Entscheidend ist nur, dass die 'QF-Test ID' eindeutig ist und dass andere Knoten sich korrekt darauf beziehen. Andererseits wird die 'QF-Test ID' des 'Komponente' Knotens in der Baumansicht angezeigt und zwar nicht nur für die 'Komponente' selbst, sondern auch für Events und andere Knoten, die sich darauf beziehen. Folglich sollten 'Komponenten' aussagekräftige 'QF-Test IDs' besitzen, die auf die eigentliche Komponente im GUI hinweisen.

Wenn QF-Test einen 'Komponente' Knoten anlegt, muss es ihm automatisch eine 'QF-Test ID' zuweisen. Es tut sein Bestes, einen aussagekräftigen Namen aus den verfügbaren Informationen zu konstruieren. Die Option QF-Test ID des Parentknotens vor QF-Test ID der Komponente setzen steuert einen Teil dieses Prozesses. Sollte Ihnen eine generierte 'QF-Test ID' nicht zusagen, können Sie diese ändern. Wenn Sie dabei einen Wert wählen, der schon vergeben ist, gibt QF-Test eine Warnung aus. Haben Sie bereits Events aufgezeichnet, die sich auf diese Komponente beziehen, bietet QF-Test an, deren 'QF-Test ID der Komponente' Attribute automatisch anzupassen. Diese Automatik funktioniert nicht bei Referenzen mit variablem 'QF-Test ID der Komponente' Attribut.

Hinweis Ein häufig gemachter Fehler ist es, das Attribut 'QF-Test ID der Komponente' eines Events anstelle der 'QF-Test ID' selbst zu ändern. Dadurch wird die Verbindung zwischen dem Event und seiner Zielkomponente zerstört, was zu einer UnresolvedComponentIdException führt. Sie sollten das also nur dann tun, wenn Sie tatsächlich die Zielkomponente ändern wollen.

Für erfahrene Tester, die beim Aufbau einer Testsuite strukturiert vorgehen, dürfte das in Abschnitt 4.4 beschriebene Verfahren zum direkten Aufzeichnen von Komponenten hilfreich sein. Mit seiner Hilfe kann zunächst die gesamte Struktur der Komponenten des SUT erstellt werden, um einen Überblick zu erhalten und sinnvolle 'QF-Test IDs' zu vergeben. Anschließend werden dann die Sequenzen aufgezeichnet und die Testsuite um die Komponenten herum aufgebaut.

5.4
Klassen von Komponenten

Die Klasse einer Komponente steht für den Typ der jeweiligen Komponente und ist daher sehr wichtig. Vereinfacht gesagt: Wenn QF-Test einen Button aufnimmt, sucht es bei der Wiedergabe auch nur nach einem Button und nicht nach einer Table oder einem Tree. Die Menge der Komponenten eines GUI lässt sich also bequem entsprechend der Klassen der Komponenten partitionieren. Dies verbessert Performanz und Stabilität der Wiedererkennung und hilft Ihnen außerdem, die von QF-Test aufgezeichnete Information zu einer Komponenten mit der tatsächlichen Komponente im GUI zu korrelieren.

Neben ihrer Rolle bei der Identifikation von Komponenten ist die Klasse auch wichtig für die Registrierung verschiedener Arten von Resolvern, die großen Einfluss darauf nehmen können, wie QF-Test Komponenten behandelt. Resolver werden in Abschnitt 46.1.6 detailliert erläutert.

4.0+5.4.1
Generische Klassen

Normalerweise gibt es in jeder Technologie systemspezifische Klassen, die einen Button, eine Tabelle oder anderen Typ kennzeichnen. Für einen Button kann diese Repräsentation z.B. ein javax.swing.JButton in Java Swing, ein org.eclipse.swt.widgets.Button in Java SWT, ein javafx.scene.control.ButtonBase in JavaFX oder ein INPUT:SUBMIT in Webanwendungen sein. Um ein technologieübergreifendes Testen zu ermöglichen, vereinheitlicht QF-Test nun diese spezifischen Klassen und arbeitet mit sogenannten generischen Klassen, z.B. Button für alle vorher genannten Button Beispiele. Hiermit wird eine gewisse Unabhängigkeit von den konkreten technischen Klassen hergestellt. Dieses Konzept ermöglicht es Ihnen, Tests unabhängig von der konkreten Technologie zu erstellen. Sie finden eine genaue Beschreibung der bestehenden generischen Klassen in Kapitel 53. Zusätzlich zu den generischen Klassen werden systemspezifische Klassen als 'Weitere Merkmale' aufgenommen, allerdings mit dem Status "Ignorieren". Im Fall von Erkennungsprobleme aufgrund zu vieler ähnlicher Komponenten können diese aktiviert werden, um die Erkennung zu schärfen, wenn auch auf Kosten der Flexibilität.

Ein weiterer Grund für generische Klassen ist, dass sich konkrete technische Klassen während der Entwicklung ändern können, z.B. wenn eine neue Technologie oder ein neues Framework eingesetzt werden. Solche Fälle erfordern von QF-Test eine große Flexibilität in der Erkennung von Klassen. Das Konzept der generischen Klassen erlaubt es Ihnen, mit diesen Änderungen umzugehen und Sie können Ihre Tests größtenteils weiterverwenden. Näheres hierzu finden Sie auch im Abschnitt Abschnitt 5.4.3.

Web5.4.2
Klassenaufbau in Webanwendungen

Bei Swing, FX und SWT arbeitet QF-Test mit den konkreten Java GUI Klassen, während bei Webanwendungen folgende pseudo Klassenhierarchie verwendet wird:

Pseudo Klassenhierarchie für Elemente von Webanwendungen
Abbildung 5.3:  Pseudo Klassenhierarchie für Elemente von Webanwendungen

Wie zu sehen, ist "NODE" die Wurzel der pseudo Klassenhierarchie. Diese Klasse passt auf jedes Element des DOM. Von "NODE" abgeleitet sind "DOCUMENT", "FRAME", "DOM_NODE" und "DIALOG", die Knotentypen, die das pseudo DOM API implementieren, welches in Abschnitt 45.1 beschrieben ist. "DOM_NODE" wird an Hand des Tag-Namens des Knotens weiter spezialisiert, z.B: "H1", "A" oder "INPUT", wobei es für manche Tags zusätzliche Unterklassen wie "INPUT:TEXT" gibt.

5.4.3
Einstellungen zur Aufnahme von Klassen

QF-Test kann Klassen von Komponenten auf unterschiedliche Arten aufzeichnen. Hierzu gliedert QF-Test Komponentenklassen in unterschiedliche Kategorien. Diese Kategorien sind die konkrete Klasse, die technologiespezifische Basisklasse, die generische Klasse sowie der spezielle Typ der generischen Klasse. Jede Kategorie wird unter 'Weitere Merkmale' aufgezeichnet.

Die Option Generische Klassen für Komponenten aufzeichnen ist die Standardeinstellung und bewirkt, dass generische Klassen aufgezeichnet werden. Mit dieser Einstellung können Ihre Tests auch für unterschiedliche Technologien mit minimalen Anpassungen lauffähig gemacht werden.

Wenn Sie eine Java Anwendung haben, die nur auf einer Technologie aufbaut und lieber die "echten" Java Klassen sehen möchten, können Sie auch ohne generische Klassen arbeiten. Hierfür sollten Sie aber die Option Nur Systemklassen aufnehmen einschalten. Diese Option bewirkt, dass jeweils die Basisklasse der jeweiligen Java-Technologie aufgezeichnet wird und nicht die konkrete abgeleitete Klasse. Falls Sie diese Option ausschalten, zeichnet QF-Test die konkrete Klasse des Objektes auf, welches zwar eine sehr gezielte Wiedererkennung auf Klassenebene bringt, allerdings bei Änderungen durch Refactoring der Klassen zu Anpassungsaufwand führt.

Web Bei Webanwendungen zeichnet QF-Test die Klassen wie im vorigen Kapitel (siehe Abschnitt 5.4.2) beschrieben auf. Falls Sie ein AJAX Toolkit verwenden, welches unterstützt wird, siehe Abschnitt 45.3, werden hierfür auch generische Klassen aufgezeichnet. Für diese Technologie besteht kein Bedarf die Standardoption zu verändern.

3.1+5.5
Untersuchung von Komponenten

Je nachdem, welcher Klasse eine Komponente angehört, besitzt diese bestimmte (öffentliche) Methoden und Felder die man im einem 'SUT Skript' verwenden kann, sobald man Zugriff auf ein Objekt hat (siehe Abschnitt 12.2.4). Um sie anzuzeigen wählt man entweder den Eintrag »Methoden für Komponente anzeigen...« aus dem Kontextmenü eines Knotens unterhalb des 'Fenster und Komponenten' Zweigs oder klickt im Komponentenaufnahme-Modus mit der rechten Maustaste auf die Komponente (siehe auch Abschnitt 4.4).

Web Die Methoden und Felder, die für (HTML) Elemente in einem Browser angezeigt werden, können nicht direkt mit dem von rc.getComponent() zurückgelieferten Objekt verwendet werden. Es sind JavaScript-Methoden und -Eigenschaften, die in evalJS eingebettet werden müssen (vgl. Abschnitt 45.1).

5.6
Warum Namen so wichtig sind

Die Automatisierung von Tests kann deutlich verbessert werden, wenn die Entwickler des SUT vorausgeplant haben oder bereit sind, durch Vergabe von Namen für zumindest einen Teil der Komponenten des SUT mitzuhelfen. Solche Namen haben zwei Effekte: Sie erleichtern QF-Test das Ermitteln der Zielkomponente für einen Event und sie haben in der Testsuite eine sehr hohe Sichtbarkeit, da sie als Basis für die 'QF-Test ID' Attribute der 'Komponenten' dienen. Letzteres sollte nicht unterschätzt werden, speziell für Komponenten ohne besondere Merkmale. Knoten, die Text in Felder namens "textName", textAddress" oder "textAccount" einfügen, sind wesentlich leichter zu verstehen und zu warten als solche für die Felder "text", "text2" oder "text3". Der koordinierte Einsatz von Name ist einer der entscheidenden Faktoren für die Effizienz der Automatisierung und für die mit QF-Test erzielbaren Einsparungen. Sollte sich die Entwicklungsabteilung oder die Projektleitung trotz des minimalen Aufwands nicht mit der Vergabe von Namen anfreunden können, geben Sie ihnen einfach dieses Kapitel des Handbuchs zu lesen.

Hinweis Bitte beachten Sie, dass Namen im Attribut 'Name' von 'Komponente' Knoten abgelegt werden. Da sie auch als Basis für die 'QF-Test ID' des selben Knotens dienen, sind 'Name' und 'QF-Test ID' oft identisch. Denken Sie aber immer daran, dass die 'QF-Test ID' ausschließlich innerhalb von QF-Test verwendet wird, wogegen der 'Name' eine entscheidende Rolle bei der Wiedererkennung der Komponente im SUT spielt. Falls sich der Name einer Komponente ändert, muss also das 'Name' Attribut angepasst werden, die 'QF-Test ID' kann beibehalten werden.

Wie Namen für Komponenten gesetzt werden können, hängt von der Art des SUT ab:

Swing Alle AWT und Swing Komponenten sind von der AWT Klasse Component abgeleitet. Deren setName Methode ist daher der Standard für Swing SUTs. Dank dieses Standard machen manche Entwickler auch unabhängig von Plänen für eine Testautomatisierung davon Gebrauch, was eine große Hilfe ist.

JavaFX Für JavaFx setId ist das Gegenstück zur setName Methode bei Swing, um Namen für Komponenten (hier "Knoten" genannt) zu vergeben. Alternativ können IDs mittels FXML über das Attribut fx:id gesetzt werden. Obwohl IDs von Knoten eindeutig sein sollen, wird dies nicht erzwungen. Dies ist analog zum 'ID' Attribut bei HTML Elementen.

SWT Leider hat SWT kein eigenes Konzept für die Vergabe von Namen. Eine akzeptierte Konvention ist der Gebrauch der Methode setData(String key, Object value) mit dem String "name" als Schlüssel und dem gewünschten Namen als Wert. QF-Test wertet diese Daten - falls vorhanden - aus und verwendet sie als Namen für die Komponenten. Mangels eines echten Standard für die Vergabe von Namen kommen diese in SWT Anwendungen inklusive Eclipse nur in Ausnahmefällen zum Einsatz.
Glücklicherweise kann QF-Test Namen für die Hauptkomponenten von Eclipse/RCP Anwendungen aus den zugrunde liegenden Modellen ableiten, was zu guten Ergebnissen führt, vorausgesetzt es wurden IDs für diese Modelle vergeben. Weitere Details finden Sie bei der Beschreibung der Option Automatische Namen für Komponenten in Eclipse/RCP Anwendungen.

Web Der naheliegende Kandidat für den Namen eines DOM Knotens ist sein 'ID' Attribut, nicht zu verwechseln mit dem 'QF-Test ID' Attribut von QF-Test's 'Komponente' Knoten. Leider erzwingt der HTML Standard keine Eindeutigkeit von IDs. Außerdem sind 'ID' Attribute ein zweischneidiges Schwert, da sie eine wichtige Rolle bei den internen JavaScript Operationen einer Webanwendung spielen können. Daher ist es zwar nicht unwahrscheinlich, dass 'ID' Attribute vergeben wurden, sie können aber nicht so frei definiert werden wie Namen in Swing, JavaFX oder SWT Anwendungen. Zu allem Übel müssen viele DHTML und Ajax Frameworks IDs automatisch generieren, was diese als Namen ungeeignet macht. Die Option 'ID' Attribut als Name verwenden falls "eindeutig genug" bestimmt, ob QF-Test 'ID' Attribute als Namen verwendet oder nicht.

WebIm Falle einer Webapplikation, welche ein von QF-Test unterstütztes AJAX Toolkit verwendet, können Sie einen Blick in Abschnitt 45.3.3 werfen, um mehr über das Setzen eindeutiger Bezeichner für das jeweilige Toolkit zu erfahren.

Falls Entwickler ein anderes, konsistentes Schema zur Vergabe von Namen eingesetzt haben, können diese Namen durch Implementierung eines NameResolvers, wie in Abschnitt 46.1.6 beschrieben, für QF-Test zugänglich gemacht werden.

Der Grund für den gewaltigen Einfluss von Namen ist die Tatsache, dass diese die Wiedererkennung von Komponenten über lange Zeit und viele Änderungen hinweg zuverlässig ermöglicht. Eine Komponente zu finden, die einen eindeutigen Namen besitzt, ist offensichtlich trivial. Ohne diese Hilfe verwendet QF-Test viele verschiedene Arten von Informationen, um eine Komponente zu lokalisieren. Der Algorithmus ist fehlertolerant und wurde fein abgestimmt, so dass er ausgezeichnete Ergebnisse erzielt. Und dennoch: Mit Ausnahme des Namens kann sich jede Information zu einer Komponente ändern, wenn sich das SUT weiterentwickelt. Irgendwann, wenn größere Änderungen vorgenommen wurden oder sich mehrere kleinere Änderungen summiert haben, wird eine Komponente nicht mehr erkannt werden und ein manueller Eingriff vonnöten sein, um die Testsuite anzupassen.

Ein weiterer wichtiger Aspekt von Namen ist, dass sie das Testen von Applikationen, deren Oberfläche in verschiedene Sprachen übersetzt wird, von der aktuell eingestellten Sprache unabhängig macht, da der Name nur intern vergeben wird und nie übersetzt werden muss.

5.7
Erwägungen zur Vergabe von Namen

Es gibt eine kritische Anforderung für Namen: Sie dürfen sich nicht im Lauf der Zeit ändern, nicht von einer Version der SUT zur nächsten, nicht von einem Aufruf zum anderen und nicht während der Ausführung des SUT, z.B. wenn eine Komponente zerstört und später neu erstellt wird. Ist ein Name einmal vergeben, muss er Bestand haben. Leider gibt es kein automatisches Schema zur Vergabe von Namen, das diese Anforderungen erfüllt. Solche Systeme erstellen Namen meist aus dem Namen der jeweiligen Klasse und einem laufenden Index, was unweigerlich fehlschlägt, da der Name dann von der Reihenfolge der Erstellung der Komponenten abhängt. Da Namen eine so zentrale Rolle bei der Erkennung von Komponenten spielen, können unzuverlässige Namen, insbesondere automatisch generierte, sehr negative Effekte haben. Falls die Entwickler nicht überzeugt werden können, derartige Namen durch vernünftige zu ersetzen, oder sie zumindest wegzulassen, können solche Namen mit Hilfe eines NameResolvers unterdrückt werden. Weitere Informationen hierzu finden Sie in Abschnitt 46.1.6.

Es ist für die Arbeit mit QF-Test nicht nötig, Namen flächendeckend zu vergeben. Allzu ausgiebiger Gebrauch kann sogar kontraproduktiv sein, da QF-Test ein eigenes Konzept dafür hat, ob eine Komponente "interessant" ist oder nicht. Uninteressante Komponenten werden wegabstrahiert und können so bei einer Änderung keine Probleme verursachen. Typische Beispiele für solche Komponenten sind Panels, die nur für Layout-Zwecke eingebaut werden. Eine Komponenten mit nicht trivialem Namen gilt für QF-Test immer als interessant, so dass die Benamung von unwichtigen Komponenten zu Problemen führen kann, wenn diese in einer späteren Version aus der Hierarchie entfernt werden.

Auch müssen Namen nicht global eindeutig vergeben werden. Jede Klasse von Komponenten bildet einen eigenen Namensraum, so dass es keinen Konflikt gibt, wenn ein Textfeld und ein Button den selben Namen haben. Auch sollten nur jeweils unter den Komponenten eines Fensters die Namen eindeutig sein. Ist dies der Fall, können Sie die Optionen Gewichtung von Namen (Wiedergabe) und Gewichtung von Namen (Aufnahme) auf "Name übertrifft alles" setzen, die flexibelste Einstellung zur Wiedererkennung von Komponenten. Sind die Namen nicht pro Fenster eindeutig, aber gleichnamige Komponenten zumindest in verschieden benamten Parent-Komponenten untergebracht, ist "Hierarchie von Namen" die nächstbeste Einstellung.

Zwei Fragen sind noch offen: Welche Komponenten sollten Namen erhalten und was sind eigentlich gute Namen? Eine gute Daumenregel ist es, allen Komponenten, mit denen ein Anwender direkt interagieren kann, einen Namen zu geben, also Knöpfe, Textfelder, etc. Komponenten, die nicht direkt erzeugt werden, sondern automatisch als Elemente von komplexen Komponenten, brauchen keinen Namen. Dies sind z.B. die Scrollbars einer JScrollPane oder die Liste in einer JComboBox. Die komplexe Komponente selbst (im Beispiel also die JScrollPane oder JComboBox) sollte dagegen sehr wohl einen Namen haben.

Falls Namen für Komponenten nicht von Anfang an vergeben wurden und die Entwickler nur den geringstmöglichen Aufwand spendieren wollen, diese zur Verbesserung der Testautomatisierung nachzuziehen, hat sich folgende Strategie als guter Kompromiss erwiesen: Fenster, komplexe Komponenten wie Bäume und Tabellen, sowie Panels, die eine Anzahl von Komponenten zu einer Art Formular zusammenfassen, sollten einen Namen erhalten. So lange Struktur und Geometrie der Komponenten in solchen Formularen einigermaßen konsistent sind, führt dies zu einer guten Wiedererkennung und brauchbaren 'QF-Test ID' Attributen. Probleme durch individuelle Komponenten mit wechselnden Eigenschaften können von Fall zu Fall behandelt werden, entweder indem entwicklungsseitig nachträglich ein Name vergeben wird, oder mit Hilfe eines NameResolvers.

Da QF-Test "weiß", für welche Komponenten setName sinnvoll ist, bietet es die Möglichkeit, diese Komponenten herauszusuchen und sogar Namen dafür vorzuschlagen, wobei diese Namen nicht immer sinnvoll sind. Dieses Feature ist analog zum Aufnehmen von Komponenten und in der Dokumentation zur Option Hotkey für Komponenten beschrieben.

Web Die vorgeschlagenen Namen für DOM Knoten sind aktuell nur begrenzt hilfreich.

5.8
'Komponenten' aktualisieren

Es ist kaum zu vermeiden, dass sich die Komponenten des SUT im Lauf der Zeit verändern. Wie beschrieben stellt dies kein großes Problem dar, sofern Namen konsequent eingesetzt werden, da QF-Test dann mit fast jeder Art von Veränderung zurecht kommt.

Ohne Namen summieren sich Änderungen mit der Zeit und können einen Punkt erreichen, an dem die Wiedererkennung fehlschlägt. Um dieses Problem zu umgehen, sollten Sie die 'Komponenten' in QF-Test von Zeit zu Zeit an den aktuellen Stand des SUT anpassen. Dies kann mit Hilfe des Menüeintrags »Komponente(n) aktualisieren« in dem Kontextmenü geschehen, das Sie nach einem Klick mit der rechten Maustaste auf einen beliebigen Knoten unterhalb des 'Fenster und Komponenten' Knotens erhalten.

Hinweis Diese Funktion kann sehr viel Information auf einmal ändern, daher ist es schwierig zu beurteilen, ob alles wie erwartet funktioniert hat oder ob eine Komponente falsch erkannt wurde. Erstellen Sie daher immer eine eigene Sicherheitskopie, bevor Sie viele Komponenten aktualisieren. Außerdem sollten Sie 'Fenster' für 'Fenster' vorgehen und darauf achten, dass die Komponenten, die Sie aktualisieren wollen, im SUT sichtbar sind (mit Ausnahme der Menüeinträge). Stellen Sie nach jedem Schritt sicher, dass die Tests immer noch sauber laufen.

Vorausgesetzt, dass eine Verbindung zum SUT besteht, erscheint bei Aufruf dieser Funktion folgender Dialog:

Komponenten              aktualisieren Dialog
Abbildung 5.4:  Komponenten aktualisieren Dialog

Sind Sie mit mehreren SUT Clients verbunden, müssen Sie zunächst einen für die Aktualisierung auswählen.

Legen Sie fest, ob Sie nur den/die selektierten 'Komponente' Knoten selbst oder auch dessen/deren Kindknoten aktualisieren wollen.

Sie können auch Komponenten einbeziehen, die im SUT momentan nicht sichtbar sind. Dies ist vor allem für Menüeinträge hilfreich.

Die 'QF-Test ID' eines aktualisierten Knotens wird beibehalten, wenn "QF-Test ID des ursprünglichen Knotens übernehmen" gewählt ist. Andernfalls erhält der Knoten eine von QF-Test generierte 'QF-Test ID', sofern sinnvolle Informationen zur Verfügung stehen. Andere Knoten, die sich auf diese 'QF-Test ID' beziehen, werden automatisch angepasst. QF-Test prüft dabei auch Abhängigkeiten in den Testsuiten, die zum selben Projekt gehören oder die im Attribut 'Abhängige Dateien (umgekehrte Includes)' des 'Testsuite' Knotens aufgeführt sind. Diese Testsuiten werden automatisch geladen und indirekte Abhängigkeiten ebenfalls aufgelöst.

Hinweis In diesem Fall werden die geänderten Testsuiten automatisch geöffnet, damit die Änderungen gespeichert oder rückgängig gemacht werden können.

Nach der Bestätigung mit "OK" wird QF-Test versuchen, die betreffenden Komponenten im SUT zu lokalisieren und aktuelle Informationen einzuholen. Komponenten, die nicht gefunden werden können, werden übersprungen. Anschließend werden die 'Komponente' Knoten an die aktuelle Struktur des GUI im SUT angepasst, was auch zur Folge haben kann, dass Knoten verschoben werden.

Hinweis Für große Hierarchien von Komponenten kann diese äußerst komplexe Operation einige Zeit in Anspruch nehmen, in extremen Fällen sogar einige Minuten.

Diese Funktion ist besonders nützlich, wenn Namen zum ersten Mal im SUT verwendet werden. Wenn Sie bereits einige Tests erstellt haben, bevor Sie die Entwickler überzeugen konnten, Namen zu vergeben, können Sie hiermit die Namen in Ihre 'Komponenten' einbinden und gleichzeitig die 'QF-Test IDs' anpassen. Dies funktioniert am besten, wenn Sie eine SUT Version bekommen können, die bis auf die Namen mit der vorherigen Version übereinstimmt.

Hinweis Sehr wichtiger Hinweis: Das Aktualisieren von ganzen Fenstern oder Hierarchien von Komponenten ab einer gewissen Größe führt oft zu dem Versuch, Komponenten zu aktualisieren, die im Moment nicht vorhanden oder unsichtbar sind. In so einem Fall ist es sehr wichtig, falsch-positive Treffer für diese Komponenten zu verhindern. Sie können dies erreichen, indem Sie vorübergehend die 'Bonus' und 'Herabsetzung...' Optionen zur Wiedererkennung (Abschnitt 36.3.4) verändern. Setzen Sie insbesondere die 'Herabsetzung für Merkmal' auf einen Wert unterhalb des Wertes der 'Mindestwahrscheinlichkeit', also z.B. auf 49, sofern Sie ansonsten die Standardwerte verwenden. Vergessen Sie nicht, die ursprünglichen Werte hinterher wiederherzustellen.

Wenn Sie die Einstellung der Optionen Gewichtung von Namen (Wiedergabe) und Gewichtung von Namen (Aufnahme) ändern müssen, zum Beispiel weil sich Namen von Komponenten wider Erwarten als nicht eindeutig herausgestellt haben, ändern Sie zunächst nur die Option für die Aufnahme. Wenn die Aktualisierung beendet ist, ziehen Sie die Option für die Wiedergabe entsprechend nach.

5.9
Lösung von Problemen bei der Wiedererkennung

Wenn sich Ihr SUT in einer Weise verändert, die es QF-Test unmöglich macht, eine Komponente wiederzufinden, schlägt Ihr Test mit einer ComponentNotFoundException fehl. Diese sollte nicht mit einer UnresolvedComponentIdException verwechselt werden, welche durch Entfernen eines 'Komponente' Knotens aus der Testsuite oder dem Ändern des Attributs 'QF-Test ID der Komponente' eines 'Event' Knotens zu einer nicht vorhandenen 'QF-Test ID' ausgelöst werden kann.

HinweisEs gibt zwei Videos, die die Behandlung einer ComponentNotFoundException ausführlich erklären. Ein einfacher Fall wird im Video http://www.qfs.de/de/yt/cnfes40.html erläutert, einen komplexeren gibt es unter http://www.qfs.de/de/yt/cnfec40.html.

Windows Falls Sie auf Probleme bei der Wiedererkennung von Komponenten in nativen Windows-Applikationen in Prozeduren aus dem Package qfs.autowin stoßen, lesen Sie bitte in Kapitel 27 weiter.

Wenn Sie eine ComponentNotFoundException erhalten, führen Sie den Test erneut mit aktiviertem Test-Debugger aus, so dass der Test angehalten wird und Sie den Knoten, der das Problem verursacht hat, untersuchen können. Hier zahlt es sich aus, wenn 'QF-Test ID' Attribute aussagekräftig sind, da Sie verstehen müssen, welche Komponente der Test anzusprechen versucht hat. Falls Sie sich gar keinen Reim darauf machen können, was der Sinn des betreffenden Knotens sein soll, deaktivieren Sie ihn und versuchen Sie, ob der Test ohne diesen Knoten durchläuft. Es könnte sich um einen Störeffekt handeln, der bei der Aufnahme nicht gefiltert wurde, und der gar nichts zum eigentlichen Test beiträgt. Grundsätzlich sollten Ihre Tests immer auf das Minimum an Knoten reduziert werden, mit denen sich der gewünschte Effekt erzielen lässt.

Falls der Knoten erhalten bleiben muss, werfen Sie als nächstes einen Blick auf das SUT, um zu sehen, ob die Zielkomponente aktuell sichtbar ist. Wenn nicht, müssen Sie Ihren Test entsprechend anpassen, um diese Situation zu behandeln. Ist die Komponente sichtbar, überprüfen Sie anhand des Bildschirmabbilds im Protokoll, ob das auch zum Zeitpunkt des Fehlers der Fall war und versuchen Sie, den fehlgeschlagenen Knoten noch einmal als Einzelschritt auszuführen. Wenn die Ausführung nun klappt, haben Sie ein Problem mit dem Timing, das Sie durch Änderung der Optionen für Standard-Verzögerungen (Abschnitt 36.3.5) oder den Einbau eines 'Warten auf Komponente' Knotens oder eines 'Check' Knotens mit 'Wartezeit' lösen können. Als letzte Möglichkeit können Sie auch mit einer festen Verzögerung arbeiten.

Falls die Komponente sichtbar ist und die Wiedergabe kontinuierlich fehlschlägt, ist die Ursache eine Änderung an der Komponente oder einer ihrer Parent-Komponenten. Nun gilt es festzustellen, was sich geändert hat und wo. Nehmen Sie hierzu einen neuen Klick auf die Komponente auf und vergleichen Sie dann den alten und neuen 'Komponente' Knoten in der Hierarchie unterhalb von 'Fenster und Komponenten'.

Hinweis Sie können vom 'Event' Knoten direkt zum zugehörigen 'Komponente' Knoten springen, indem Sie [Strg-W] drücken oder rechts-klicken und im Popup-Menü »Komponente finden« wählen. Sie können mittels [Strg-Backspace] oder »Bearbeiten«-»Vorherigen Knoten anwählen« wieder zurück springen. Ein schlauer Trick ist, die zu vergleichenden 'Komponente' Knoten durch Setzen von Breakpoints zu markieren, um sie leichter wiederzufinden.

Der Knackpunkt ist die Stelle, an der die Hierarchie der beiden Knoten verzweigt. Wenn sie unter verschiedenen 'Fenster' Knoten angesiedelt sind, liegt der Unterschied in den betreffenden 'Fenstern' selbst. Andernfalls gibt es einen gemeinsamen Vorgänger direkt oberhalb der Verzweigung. Der entscheidende Unterschied ist dann in den jeweiligen Knoten direkt unterhalb dieses gemeinsamen Vorgängers zu finden. Wenn Sie die Stelle mit der Unterscheidung gefunden haben, vergleichen Sie die Attribute der betreffenden Knoten von oben nach unten und suchen Sie nach Abweichungen.

Hinweis Sie können mittels »Ansicht«-»Neues Fenster...« ein weiteres QF-Test Fenster öffnen und damit die Detailansichten der beiden Knoten nebeneinander platzieren.

Die einzigen Unterschiede, die immer zu einem Fehler bei der Wiedererkennung führen, sind Änderungen der Attribute 'Klasse' oder 'Name'. Abweichungen bei 'Merkmal', Struktur oder Geometrie können üblicherweise kompensiert werden, sofern sie sich nicht häufen.

Eine Änderung der 'Klasse' kann durch Refactoring seitens der Entwickler verursacht worden sein. In diesem Fall müssen Sie Ihr 'Klasse' Attribut an diese Änderung anpassen. Eine andere mögliche Ursache ist Obfuscation, eine Technik mit der die Namen der Klassen des SUT unleserlich gemacht werden, um sie vor neugierigen Blicken zu schützen. Dies stellt ein Problem dar, da die Namen der Klassen sich dadurch mit jeder Version ändern können. Probleme mit Refactoring oder Obfuscation können durch aktivieren der Option Nur Systemklassen aufnehmen vermieden werden.

Falls sich der Name geändert hat, wird es etwas schwieriger. Falls die Änderung beabsichtigt zu sein scheint, z.B. die Korrektur eines Rechtschreibfehlers, können Sie Ihr 'Name' Attribut entsprechend anpassen. Wahrscheinlicher ist, dass es sich um einen automatisch generierten Namen handelt, der sich jederzeit wieder ändern kann. Wie im vorherigen Abschnitt beschrieben, können Sie in diesem Fall das Problem mit den Entwicklern diskutieren, oder den Namen mit Hilfe eines NameResolvers unterdrücken, wie in Abschnitt 46.1.6 beschrieben.

Änderungen am Attribut 'Merkmal' sind insbesondere für 'Fenster' Knoten nicht ungewöhnlich. Dort entspricht das 'Merkmal' dem Titel des Fensters. Kombiniert mit einer signifikanten Änderung der Geometrie kann das zum Scheitern der Wiedererkennung führen. Dies kann durch Anpassen des 'Merkmal' Attributs an die neuen Gegebenheiten, oder - bevorzugt - durch Verwendung eines regulären Ausdrucks, der alle Varianten abdeckt, behoben werden.

Abhängig von Art und Umfang der Änderungen gibt es zwei grundsätzliche Möglichkeiten zur Korrektur:

  • Passen Sie die Attribute des alten Knoten an und entfernen Sie die neu aufgenommenen Knoten.
  • Behalten Sie die neuen Knoten und entfernen Sie den alten. Hierzu müssen Sie zunächst sicherstellen, dass alle Knoten, die auf die alte Komponente verweisen, an die neue 'QF-Test ID' angepasst werden. Dies lässt sich durch einen kleinen Trick erreichen: Ändern Sie die 'QF-Test ID' des alten 'Komponente' Knotens auf die 'QF-Test ID' des neuen. QF-Test beschwert sich zunächst, dass die 'QF-Test ID' nicht eindeutig ist, was Sie ignorieren können, und bietet dann an, alle Verweise zu aktualisieren, was Sie mit "Ja" bestätigen müssen. Anschließend können Sie den alten Knoten entfernen.

Hinweis Die automatische Anpassung der Verweise in anderen Testsuiten funktioniert nur, wenn diese zum selben Projekt gehören oder das Attribut 'Abhängige Dateien (umgekehrte Includes)' des 'Testsuite' Knotens korrekt gesetzt ist.

Web5.10
Zugriff auf unsichtbare Felder einer Webseite

Unsichtbare Felder (hidden fields) werden standardmäßig nicht aufgezeichnet und somit auch nicht unterhalb des 'Fenster und Komponenten' Knotens abgelegt.

Wenn Sie regelmäßig auf unsichtbare Felder zugreifen müssen, können Sie die Option Sichtbarkeit von DOM Elementen berücksichtigen deaktivieren.

Einen andere Möglichkeit bietet das folgende Vorgehen:

  • Aktivieren Sie den Modus Komponenten aufnehmen.
  • Navigieren Sie den Mauszeiger zum Eltern-Element der unsichtbaren Feldes (in den meisten Fällen wohl ein FORM Element).
  • Betätigen Sie die rechte Maustaste und wählen Sie »Komponente mit Kindern« aus dem Kontextmenü.
  • Deaktivieren Sie den Modus Komponenten aufnehmen.
  • »Bearbeiten«-»Vorherigen Knoten anwählen« bringt Sie direkt zum aufgenommenen Komponentenknoten. Eine Suche innerhalb von 'Fenster und Komponenten' nach z.B. 'HIDDEN' schnell zur Zielkomponente führen.

Das Auslesen der Attribute des unsichtbaren Feldes (z.B. das Attribut 'value') kann durch ein einfaches 'SUT Skript' geschehen, wie es unten gezeigt wird. Details zu Skripting im Allgemeinen, die genutzten Methoden und Parameter finden Sie entsprechend in Skripting, Das API des Runcontexts und Pseudo DOM API für Webanwendungen.

node = rc.getComponent('id of the hidden component', hidden=1)
          node.getAttribute('value')
        
Beispiel 5.1:  Auslesen des 'value' Attributes eines unsichtbaren Feldes