45.2
Besondere Unterstützung für verschiedene Webframeworks

Das Akronym AJAX für "Asynchronous JavaScript and XML" wird allgemein mit modernen Webanwendungen assoziiert, die sich interaktiver anfühlen als die klassischen <FORM>-basierten Anwendungen und vom Look&Feel her schon fast an Desktop-Applikationen herankommen. Hinter diesem gemeinsamen Akronym steckt allerdings ein ganzer Zoo von Webframeworks, auf denen solche Anwendungen basieren. Jedes davon setzt eigene Schwerpunkte und kommt mit einem eigenen Satz von Widgets. Solche Webframeworks stellen für QF-Test und jedes andere automatisierte Testwerkzeug aus folgenden Gründen ein Problem dar:

  • Die Komponentenhierarchie wird automatisch aus abstrakten Widgets wie Button oder List generiert. Ein Widget wird dabei oft mittels diverser <DIV> Knoten implementiert. Dies führt zu einer sehr tief verschachtelten Hierarchie mit geringer Struktur.
  • IDs werden entweder gar nicht zugewiesen oder automatisch generiert, was für Regressionstests noch problematischer ist.
  • Die asynchrone Kommunikation mit dem Webserver und die dynamische Erstellung von DOM Knoten kann Probleme beim Timing verursachen.

Es gibt kein Allheilmittel, mit dem sich diese Probleme generisch lösen lassen. In vielen Fällen kann QF-Test trotzdem ohne weiteres Zutun mit AJAX Anwendungen interagieren. Dabei sind Wiedererkennung und Performanz allerdings nicht ideal. Optimale Testbarkeit kann nur mit Hilfe von Spezialfunktionen erreicht werden, die genau auf ein Webframework zugeschnitten sind und sich dessen Eigenheiten zu Nutze machen.

Video Das Video 'Die Explosion der Komplexität in der Web Testautomatisierung eindämmen' zeigt eindrucksvoll die Reduktion tief geschachtelter DOM-Strukturen durch QF-Test.

Für die folgende Liste von Webframeworks bietet QF-Test Resolver für eine optimierte Behandlung:

Der angegebene Kurzname kann in Aufrufen der Prozedur installCustomWebResolver im Parameter resolver angegeben werden, siehe Abschnitt 45.1.3.

Framework Name Framework Webseite Kurzname
Angular http://angular.io angular
Ext JS http://www.extjs.com extjs
Google Web Toolkit (GWT) http://www.gwtproject.org gwt
ICEfaces http://icesoft.org icefaces
jQuery UI http://jqueryui.com jqueryui
jQuery EasyUI http://jeasyui.com jeasyui
Kendo UI http://telerik.com/kendo-ui kendoui
Prime Faces http://primefaces.org primefaces
Qooxdoo http://www.qooxdoo.org qooxdoo
Rich Ajax Platform (RAP) http://www.eclipse.org/rap rap
RichFaces http://www.jboss.org/richfaces richfaces
Smart GWT http://www.smartclient.com smartgwt
Vaadin http://vaadin.com vaadin
ZK http://zkoss.org zk
Tabelle 45.6:  Untertützte Webframeworks

QF-Test ist sogar in der Lage, automatisch festzustellen, ob Ihre Webanwendung eines dieser Frameworks benutzt und einen passenden Resolver, wie unten beschrieben, einzuhängen.

45.2.1
Konzepte für Webframework-Resolver

Ein Webframework-Resolver besteht aus verschiedenen Resolvern und anderen Funktionen, die speziell für ein bestimmtes Framework entwickelt werden. Vor allem versucht QF-Test, den DOM Knoten Klassen zuzuweisen, die den zugehörigen abstrakten Widgets entsprechen und Knoten auf Zwischenebenen, die nur ein Detail der Framework-Implementierung sind, aus der Hierarchie herauszufiltern. Die Attribute 'Name', 'Merkmal' und 'Weiteres Merkmal' werden passend zum Framework ermittelt und Events werden so auf den korrekten DOM Knoten wiedergegeben, dass dies möglichst exakt einer Aktion von einem echten Anwender entspricht. Diese Maßnahmen reduzieren die Hierarchie der Komponenten drastisch und erhöhen Performanz und Zuverlässigkeit der Wiedererkennung und Wiedergabe gleichermaßen. Zudem werden Timing und Synchronisation besonders unterstützt.

Zwangsläufig unterscheiden sich Komponenten und Events für eine Webanwendung mit und ohne aktiviertem Framework Resolver signifikant und sind nicht zueinander kompatibel. Daher sollte die Entscheidung, ob ein Framework Resolver verwendet wird, so früh wie möglich getroffen werden. Andernfalls müssen entweder bestehende Tests neu implementiert werden, nachdem der Resolver aktiviert wird, oder Tests mit und ohne Resolver müssen sauber voneinander getrennt werden. Wenn ein Resolver für Ihre Anwendung verfügbar ist, sollten Sie ihn praktisch immer auch einsetzen, außer Ihre Tests sind bereits zu umfangreich, weitgehend vollständig und stabil.

Die Implementierung eines Webframework Resolvers ist ein fortlaufender Prozess. Da Änderungen an einem Resolver Auswirkungen darauf haben können, wie Komponenten aufgenommen und erkannt werden, muss sichergestellt sein, dass Sie Ihre QF-Test Version aktualisieren können, ohne die Kompatibilität bestehender Tests zu gefährden. Hierzu werden Framework Resolver mit einer eigenen dreistelligen Version versehen, beginnend mit Version 1.0.0, mit folgender Bedeutung:

  • Bei einer Änderung der Minor Version, z.B. 1.0.1, ist die Kompatibilität nicht berührt.
  • Eine Änderung der Medium Version, z.B. 1.1.0, bedeutet, dass mit niedrigerer Medium Version aufgenommene Tests immer noch wiedergegeben werden können, bei Aufnahme neuer Sequenzen aber Komponenten anders aufgenommen werden können. Dies ist nicht kritisch, es kann aber besser sein, solche Neuaufnahmen zu vermeiden, wenn die Vorteile der neuen Version nicht überwiegen.
  • Bei einer Änderung der Major Version, z.B. 2.0.0, kann auch die Kompatibilität der Wiedergabe verloren gehen, was dann eine Neuaufnahme oder manuelle Anpassung der betreffenden Komponenten erforderlich macht.

Webframework Resolver werden über die 'Prozedur' qfs.web.ajax.installCustomWebResolver in der Standardbibliothek qfs.qft aktiviert, bei der Sie die zu verwendende Version angeben müssen. Sie können wahlweise nur die Major Version angeben, in welchem Fall QF-Test die höchste verfügbare Medium.Minor Version für diese Major Version verwendet. Dies ist üblicherweise die beste Option und wird in der mit Hilfe des Schnellstart-Assistenten erstellten Startsequenz verwendet (vgl. Kapitel 3). Alternativ können Sie die Major.Medium Version festlegen, oder sogar die exakte Major.Medium.Minor Version und so Ihre Tests mit der Version des Resolvers ausführen, mit der sie erstellt wurden.

45.2.2
Eindeutige Bezeichner setzen

Jedes Webframework hat seine eigene Methoden, um eindeutige IDs zu vergeben. In diesem Abschnitt finden Sie die entsprechenden Methoden für die unterstützten Frameworks von QF-Test:

45.2.2.1
Angular

Die einfachste Variante ist es, das 'ID' Attribut <div id="myId"/> für alle notwendigen Komponenten zu setzen.

45.2.2.2
Ext JS

IDs können mittels folgendem Code gesetzt werden:
var container = Ext.create('Ext.container.Container', {
id: 'MyContainerId',
... });
.

Als Alternative können Sie auch container.getEl().set({ 'qfs-id': 'myId' }); aufrufen. In diesem Fall müssen Sie allerdings einen NameResolver implementieren, der 'qfs-id' als Namen für QF-Test setzt.

45.2.2.3
GWT

Die einfachste Variante ist die Methode widget.getElement().setId("myId"); für die erzeugten Elemente aufzurufen.

Alternativ können Sie auch widget.ensureDebugId("myId") aufrufen. Allerdings müssen Sie in diesem Fall die Datei xxx.gwt.xml anpassen, damit diese IDs auch wirklich gesetzt werden. Hierfür müssen Sie <inherits name="com.google.gwt.user.Debug"/> eintragen.

Es ist auch möglich ein eigenes Attribut 'qfs-id' für die Identifikation zu setzen. Hierfür rufen Sie die Methode setAttribute("qfs-id", "myId") auf. Dieses Attribut kann nun mittels NameResolver für QF-Test verwendet werden.

45.2.2.4
ICEfaces

Die einfachste Variante ist es, das 'ID' Attribut <p:inputText id="myId"/> für alle notwendigen Komponenten in der xhtml Definition zu setzen.

45.2.2.5
jQuery UI

Die einfachste Variante ist es, das 'ID' Attribut <p:inputText id="myId"/> für alle notwendigen Komponenten zu setzen, bei einem existierenden Element wie folgt: $(element).attr("id","myId");

45.2.2.6
jQuery EasyUI

Die einfachste Variante ist es, das 'ID' Attribut <p:inputText id="myId"/> für alle notwendigen Komponenten zu setzen.

45.2.2.7
Kendo UI

Sie müssen das 'ID' Attribut im Sourcecode oder über den grafischen Editor setzen.

45.2.2.8
PrimeFaces

Die einfachste Variante ist es, das 'ID' Attribut <p:inputText id="myId"/> für alle notwendigen Komponenten in der xhtml Definition zu setzen.

45.2.2.9
Qooxdoo

Es gibt keinen Standardweg. Sie können entweder ein eigenes Attribut in der Generierung des DOMs an die Knoten oder eine Eigenschaft an die setData Methode des Qooxdoo Widgets hängen. Diese Eigenschaft können Sie dann per Resolver auswerten.

45.2.2.10
RAP

Ab RAP Version 2.2 wird ein Name, der mit widget.setData("name", "myId") vergeben wird, genau wie bei SWT direkt von QF-Test ausgewertet. Das Feld kann nur benutzt werden wenn es zuvor über WidgetUtil.registerDataKeys("name"); registriert wurde.

Für RAP Versionen älter als 3.0.0 funktioniert auch die folgende Technik, die aber nicht empfohlen wird, da sie vom SWT Standard abweicht und zuätzlich erfordert, den Webserver mit einer besonderen Option zu starten.:

Rufen Sie die Methode widget.setData(WidgetUtil.CUSTOM_WIDGET_ID, "myId"); für jedes notwendige Element auf.

Nun müssen Sie noch Ihre Webserver Umgebung mit folgendem zusätzlichen Parameter starten -Dorg.eclipse.rap.rwt.enableUITests=true.

Bitte beachten: Der VM Parameter wurde ab RAP 2.0 umbenannt, für RAP Versionen vor 2.0 lautet er -Dorg.eclipse.rwt.enableUITests=true.

45.2.2.11
RichFaces

Sie müssen das 'ID' Attribut im Sourcecode oder über den grafischen Editor setzen.

45.2.2.12
Smart GWT

Die einfachste Variante ist es, die Methode widget.setID("id") für alle notwendigen Komponenten aufzurufen.

45.2.2.13
Vaadin

Die einfachste Variante ist es, die Methode widget.setId("id") (widget.setDebugId("id") für Vaadin Version < 7) für alle notwendigen Komponenten aufzurufen.

Sie können auch eine eigene Stylesheet Klasse mittels widget.setStyleName("qfs-id=myId") hinzufügen. Diese muss dann in einem NameResolver für QF-Test ausgewertet werden.

45.2.2.14
ZK

QF-Test verwendet die Widget-ID, welche auch in den zul Dateien verwendet wird. Daher sollten die meisten IDs nutzbar sein.

Das ZK Framework bietet auch einen eigenen IDGenerator an, um IDs zu vergeben. Dies kann allerdings ziemlich aufwendig sein, hier ist es besser sich auf die Standardalgorithmen von QF-Test zu verlassen.