![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
Version 5.2.2 |
| Komponenten |
Zum Thema "Komponenten" gibt es mehrere Videos:
Das Video 'Komponentenerkennung' erläutert
zunächst die Wiedererkennungskriterien für Komponenten, danach (ab Minute 13:07) werden generische Komponenten
erläutert, zuerst solche mit regulären Ausdrücken, danach solche mit Variablen für die
Wiedererkennungsmerkmale.
Es gibt zwei Videos, die die Behandlung einer ComponentNotFoundException
ausführlich erklären:
Ein einfacher Fall wird im Video 'ComponentNotFoundException - einfacher Fall' erläutert.
Einen komplexeren Fall gibt es unter 'ComponentNotFoundException - komplexer Fall'.
Das Video 'Die Explosion der Komplexität in der Web Testautomatisierung eindämmen' zeigt eindrucksvoll den Umgang von QF-Test mit tief geschachtelten DOM-Strukturen.
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:
| 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:
| ![]() |
||
| 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
.
WebDie 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.
| '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:
| ![]() |
||
| 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.
Hinweis 4.0+ Neben dieser Möglichkeiten Komponenten als Knoten darzustellen ist es auch möglich, Komponenten mithilfe einer XPath-ähnlichen Syntax namens QPath zu adressieren. Diese Syntax wird in Abschnitt 6.3.2 erläutert.
Die Attribute von 'Komponenten' und der Algorithmus zur Wiedererkennung werden ausführlich in Abschnitt 44.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 47.
| '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.
| 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 49.1.6 detailliert erläutert.
| 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 56. 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.
| 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:
| ![]() |
||
| 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 49.11 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.
| 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 46.2, werden hierfür auch generische Klassen aufgezeichnet. Für diese Technologie besteht kein Bedarf die Standardoption zu verändern.
| 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 49.11).
| 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 46.2.2 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 49.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.
| 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 49.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.
| '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:
| ![]() |
||
| 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 37.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.
| 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.
Es gibt zwei Videos, die die Behandlung einer
ComponentNotFoundException
ausführlich erklären:
Ein einfacher Fall wird im Video 'ComponentNotFoundException - einfacher Fall' erläutert.
Einen komplexeren Fall gibt es unter 'ComponentNotFoundException - komplexer Fall'.
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 47 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 37.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 49.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:
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.
| 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:
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.
|
|
|||
| Beispiel 5.1: Auslesen des 'value' Attributes eines unsichtbaren Feldes |
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | Letzte Änderung: 11.2.2021 Copyright © 1999-2021 Quality First Software GmbH |