5.0+15
Testen nativer Windows-Anwendungen

Einstieg

Video Video über das Testen von Native Windows Desktop Applicationen: 'QF-Test Version 5.0 - Windows Anwendungen testen'.

Dieses Kapitel behandelt das automatisierte Testen von Windows-Desktop-Anwendungen, insbesondere

  • klassische Win32-Anwendungen,
  • .NET-Anwendungen, welche auf den Frameworks Windows Presentation Foundation (WPF) oder Windows Forms basieren und
  • Universal Windows Platform (UWP) Anwendungen, welche XAML-Steuerelemente verwenden.

Die genannten Anwendungstypen unterstützen die Microsoft UI Automation oder die Microsoft Active Accessibility (MSAA) Schnittstellen. Weiterführende Informationen zu diesen, unter dem Namen Windows Automation API zusammengefassten Schnittstellen, wurden im Abschnitt 15.2 zusammengetragen.

Für die Testausführung benötigt QF-Test eine Verbindung zu dem Prozess der zu testenden Anwendung. Zur Erstellung einer 'Vorbereitung', welche eine solche Verbindung herstellt, bietet sich der Erzeugung der Startsequenz - Schnellstart-Assistent an, welcher über das Menü »Extras« aufgerufen werden kann. Wählen Sie 'Eine native Windows-Anwendung' als Anwendungstyp. Weiterführende Informationen zur Benutzung des Schnellstart-Assistenten können Sie Abschnitt 15.3 und Abschnitt 3.1 entnehmen.

Um sich mit einer bereits laufenden Anwendung zu verbinden, können Sie den 'Windows-Anwendung verbinden' Knoten verwenden. Hierbei reicht es den Titel des (Haupt-)Fensters anzugeben. Hierbei können Sie auch reguläre Ausdrücke verwenden. Falls dies der Fall ist, müssen Sie zusätzlich die CheckBox 'Als Regexp' aktivieren. Für den Windows Editor (Notepad) wäre dies zum Beispiel .*- Editor. Hierbei sollte allerdings darauf geachtet werden, dass der angegebene reguläre Ausdruck nicht zufällig mit dem Titel eines anderes Fenster übereinstimmt. Wenn die Anwendung durch QF-Test gestartet werden soll, verwenden Sie bitte den 'Windows-Anwendung starten' Knoten und geben Sie die ausführbare Datei (.exe) Ihrer Anwendung inklusive Pfad an, vgl. Start/Anbindung einer Applikation.

Wenn sich QF-Test zu der Anwendung (als 'GUI-Engine'win) verbunden hat, können Tests aufgenommen und abgespielt werden wie in Kapitel 4 beschrieben. Auf Grund der Eigenschaften der Microsoft UI Automation sind allerdings die in Abschnitt 15.4 aufgeführten Aufnahmeregeln zu beachten.

Die Installation von QF-Test liefert folgende Beispiel-Testsuiten mit:

  • qftest-7.1.2/demo/carconfigForms/winDemoForms_de.qft
  • qftest-7.1.2/demo/carconfigWpf/winDemoWPF_de.qft
  • qftest-7.1.2/demo/windows/Win10Calculator_de.qft

Bitte beachten Sie auch die (aktuellen) Einschränkungen, Abschnitt 15.9, von denen zu erwarten ist, dass die meisten in zukünftigen QF-Test Releases behoben oder verbessert werden.

Technischer Hintergrund

Ein verbreitetes Framework für Windows basierte Applikationen ist die Windows Automation API, bestehend aus der Microsoft Active Accessibility und dessen Nachfolger, der Microsoft UI Automation. Dies ist das Kernstück der win Engine, wodurch QF-Test in der Lage ist, fast alle Arten von Windows Applikationen zu steuern.

Eine Windows-Anwendung muss sogenannte Provider zur Verfügung stellen, um die Regeln der UI Automation einzuhalten. Dies geschieht bei der Verwendung eines Frameworks wie WPF automatisch, bei Win32 Applikationen über Proxy Provider. Wie gut eine Applikation gestestet werden kann, hängt somit von der Qualität der jeweiligen Provider ab, d.h. dem Framework, welches für die Entwicklung verwendet wurde. Da die UI Automation zusammen mit dem WPF Framework eingeführt wurde, sollten Anwendungen, die damit entwickelt wurden, gut testbar sein. Bei Entwicklungsplattformen ohne Integration der UI-Automation sieht die Sache anders aus, wie zum Beispiel bei Java Swing. Aber dafür für Java-Anwendungen stellt QF-Test auch einen ziemlich guten anderen Verbindungsmodus bereit ...

Wenn ein Programm über UI Automation getestet werden soll, so stehen sogenannte Automation Elements zur Verfügung, die die eigentlichen UI Elemente der zu testenden Anwendung darstellen. Obwohl jedes Automation Element einen Control Type hat (Button, MenuItem etc.), wird seine tatsächliche Funktionalität - zum Beispiel das Setzen eines Wertes in einem Textfeld - über Control Patterns bestimmt, die über den jeweiligen Provider implementiert sind.

Zur Bedienung des UI Automation Frameworks startet QF-Test ein spezielles Java Programm, das als UI Automation Client Applikation dient. Dieses Programm kann alle UI Automation Elemente eines bestimmten Prozesses ansprechen und diese entsprechend der QF-Test Regeln bedienen (zum Beispiel zum Erstellen eines Abbildes eines Elements als 'Komponente').

Start/Anbindung einer Applikation

Um eine native Windows-Anwendung zu testen ist es nicht zwingend notwendig, diese Anwendung über QF-Test zu starten. Man kann QF-Test auch mit einem bereits laufenden Prozess verbinden. Dadurch ist es auch möglich, Bereiche des Betriebssystems zu steuern, zum Beispiel die Windows Taskbar.

Die Anbindung an einen bereits laufenden Prozess erfolgt entweder über den Fenstertitel (wahlweise mit regulärem Ausdruck), die Prozess-Id oder den Klassennamen des Fensters, der über die UI Automation bereitgestellt wird. Die Anbindung ist für ein Window im Sinne eines UI Automation Control Types möglich, aber auch für ein Pane oder Menu Element. Unabhängig von der gewählten Verbindungsmethode, ermittelt QF-Test die jeweilige Prozess-Id und wird genau diesen Prozess als System Under Test (SUT) behandeln.

Der 'Windows-Anwendung verbinden' Knoten stellt die Verbindung her. Dabei muss für die Verbindung zu einer bereits laufenden Anwendung im Attribut 'Fenstertitel' einer der folgenden Werte eingetragen werden (wie bereits oben erwähnt):

  • ein regulärer Ausdrück für den Fenstertitel
  • -pid <Prozess-Id>
  • -class <class name>

Beispiele:

.*- Editor: zur Anbindung an einen laufenden Windows Notepad Prozess,

-class Shell_TrayWnd: Anbindung der Windows Taskbar verbinden.

Für die Ermittlung des Fenstertitels, der Prozess-Id oder des Class Name des laufenden Programms steht die Prozedur qfs.autowin.logUIAToplevels in der Standardbibliothekqfs.qft zur Verfügung.

Man kann die zu testende Anwendung aber auch direkt über den 'Windows-Anwendung starten' Knoten starten. In diesem Fall geben Sie den Dateinamen der ausführbaren Datei, inklusive Pfad, im Attribut 'Windows-Anwendung' an.

Sie können auch das Attribut 'Windows-Anwendung' zusammen mit dem 'Fenstertitel' Attribut angeben. Dies ist nützlich, wenn die Anwendung gestartet werden soll, falls sie nicht bereits läuft. QF-Test prüft dann zuerst, ob es sich an einen laufenden Prozess, der dem 'Fenstertitel' Attribut entspricht, anbinden kann. Falls nicht, wird das angegebene Programm gestartet und über seine Prozess-Id verbunden. Es kann vorkommen, dass dieser Prozess einen weiteren Prozess startet, der das eigentliche Programm darstellt, wobei ersterer selbst aber keine (grafische) Benutzeroberfläche hat oder sich sogar beendet. In diesem Fall wird ein weiterer Versuch durchgeführt um eine Verbindung zu dem zweiten Prozess zu erlangen.

Wenn Sie in QF-Test einen win Client beenden (entweder mittels des 'Programm beenden' Knotens oder über das »Clients« Menü), wird der entsprechende UI Automation Client Prozess mitsamt seiner Unterprozesse gestoppt. Das heißt, dass die zu testende Anwendung nur dann beendet wird, wenn sie aus QF-Test heraus gestartet wurde, nicht aber, wenn sie bereits vor der Verbindung mit QF-Test gelaufen ist.

Wenn sie die zu testende Anwendung beenden, wird in jedem Fall auch der UI Automation Client beendet.

Um sich mit einem heraufgestuften Prozess verbinden zu können, muss QF-Test als Administrator gestartet werden.

Aufnahme

Nach erfolgreicher Verbindung von QF-Test mit der zu testenden Anwendung können Sie mit der Aufnahme von Aktionen (Abschnitt 4.1), Checks (Abschnitt 4.3) und Komponenten (Abschnitt 4.4) beginnen.

Da die Kommunikation zwischen dem QF-Test UI Automation Client und der zu testenden Anwendung über Windows (konkret, den UI Automation Core) läuft, ist der Zugriff auf die Komponenten nicht ganz so schnell wie Sie dies vielleicht von der QF-Test Java-Automatisierung kennen. Außerdem werden Events im Gegensatz zu Java- oder Web-Tests (QF-Driver) asynchron verarbeitet. Das bedeutet, dass Sie nicht davon ausgehen können, dass der Dispatch Thread der Applikation geblockt wird während QF-Test ein Ereignis bearbeitet.

Dies macht Aufnahmen schwieriger, wenn die Zielkomponente in Folge der aufzunehmenden Aktion verschwindet bevor QF-Test die Komponentenidentifizierung abgeschlossen hat. Zum Beispiel bei der Aufnahme eines Combobox-Eintrags, der die Liste nach dem Klick sofort schließt, oder eines Buttons, der das Fenster, in dem er liegt, beendet.

Daher ist es sinnvoll, wenn Sie folgende Vorgehensweise beachten:

  • Aktivieren Sie den Aufnahmemodus und bewegen Sie die Maus zu dem Element, für das Sie eine Aktion aufnehmen wollen.
  • Da QF-Test etwas Zeit benötigt um das Element unter dem Mauszeiger zu identifizieren, wird ein rotes Panel angezeigt bis der Vorgang abgeschlossen ist. In dem kleinen 'QF-Test Element Information' Fenster sehen Sie dann, welche Komponente erkannt wurde.
  • Führen Sie nun die aufzunehmende Aktion aus.
  • Wenn Sie einen Mausklick aufnehmen, der einen Dialog oder ein Fenster schließt (auch Popup-Listen), halten Sie die Maustaste ein wenig länger gedrückt, so dass QF-Test die Möglichkeit hat, die nötigen Informationen auszulesen bevor das Fenster verschwindet, was häufig fast zeitgleich mit dem Loslassen der Maustaste geschieht.
  • Bei der Aufnahme von Checks oder Komponenten erscheint ein Rahmen um das Element sobald der Mauszeiger darüber fährt. Bitte warten Sie mit der Aufnahme bis der Rahmen wieder verschwunden ist.

Wenn Sie bei der Aufnahme einer Aktion Probleme haben, weil diese zum Beispiel das entsprechende Fenster schließt (Klick auf OK oder Abbrechen Button), kann es hilfreich sein, einen Check auf die entsprechende Komponente aufzunehmen und diesen dann in die gewünschte Aktion zu konvertieren. Manchmal kann das Drücken der Maustaste auch dazu führen, dass ein Element neu generiert wird (zum Beispiel bei der Zubehörtabelle im CarConfiguratorNet WPF Demo). Auch hier kann die Check-Aufnahme helfen. Im Check-Aufnahmemodus legt QF-Test ein (fast) unsichtbares Fenster über die zu testende Anwendung um so zu verhindern, dass Mausklicks eine Aktion in der Anwendung bewirken.

Komponenten

Ein UI Automation Element wird von QF-Test als 'Fenster' beziehungsweise 'Komponente' innerhalb des 'Fenster und Komponenten' Knotens aufgenommen. Ein manuelles Einfügen von Knoten ist natürlich auch möglich. Die (generische) QF-Test 'Klasse' entspricht häufig dem Type des UI Automation Elements, zum Beispiel bei Button. Um den Type vom Klassennamen unterscheiden zu können, setzt QF-Test das Präfix Uia. vor den Type. Analog wird der Kurzname des UI Automation Frameworks als Präfix für die UI Automation Class des Elements verwendet. Zum Beispiel würde QF-Test bei einer Tabelle einer WPF-Anwendung in 'Weitere Merkmale' des 'Komponente' Knotens einen Eintrag mit classname: WPF.DataGrid anlegen.

QF-Test bildet die Hierarchie der UI Automation Elemente unter Umständen nicht eins zu eins im Komponentenbaum ab. Dies geschieht häufig bei Dialogen (wie zum Beispiel dem Schriftart-Dialog von Notepad), die üblicherweise in der Komponentenhierarchie der UI Automation unter dem Hauptfenster aufgeführt werden. Aus der Sicht von Win32, genauso wie das auch QF-Test Anwender erwarten würden, sind diese Dialoge top-level Windows und damit in 'Fenster und Komponenten' parallel zum Hauptfenster angeordnet. Andererseits kann ein Kontextmenü, das ganz oben in der UI Automation Hierarchie angesiedelt ist, in QF-Test innerhalb eines Fensters zu finden sein.

Wiedergabe und Patterns

Die win Engine unterstützt neben den bereits aus anderen Engines bekannten Mausklicks auch verschiedene Spezialaktionen die nicht auf Mausklicks basieren.

Zum Beispiel kann die Aktion einer Schaltfläche mittels

  +Auswahl: invoke [myButtonID]

ausgelöst werden. Die Wirkung sollte die gleiche sein wie bei

  +Mausklick [myButtonID]

Bei einem 'Auswahl' wird die Maus nicht verwendet. Stattdessen löst der UI Automation Prozess die Ausführung einer Invoke() Methode des Providers im SUT aus.

Der 'Auswahl' Knoten unterstützt die folgenden Aktionen im Attribut 'Detail': invoke, expand, collapse, select, toggle und scroll. In der nachfolgenden Tabelle werden sie detailiert beschrieben:

'Detail'BeschreibungPattern
invokeMeist gleichwertig mit einem Mausklick.InvokePattern
expand, collapseDies sollte eine Combobox, ein MenuItem oder ein TreeItem aus- beziehungsweise einklappen.ExpandCollapsePattern
select[:0|-1|1]Wählt einen Listeneintrag aus. Wenn als Detail -1 bzw. 1 angegeben wird, so wird eine Mehrfachauswahll erweitert oder verringert.SelectionItemPattern
toggle[:on|off]Ändert den Zustand einer CheckBox.TogglePattern
scroll:horiz%,vert%Erlaubt Werte zwischen 0 und 100, die die Scroll-Position in Prozent angeben. -1, wenn die Position (Horizontal oder vertikal) nicht verändert werden soll.ScrollPattern
Tabelle 15.1:  Unterstützte Details für 'Auswahl'

Welche Aktionen tatsächlich auf einem Control abgespielt werden können, hängt davon ab, welche Pattern das entsprechende UI Automation Elements implementiert. Die verfügbaren Patterns werden unter 'Weitere Merkmale' einer Komponente abgespeichert oder können in einem 'SUT-Skript' mit dem Befehl print rc.getComponent(id).getPatterns() ermittelt werden.

Die genaue Bedeutung eines Patterns kann sich von Anwendung zu Anwendung unterscheiden. Wenn sowohl das SelectionItem-Pattern als auch das Invoke-Pattern unterstützt werden, sollte invoke bevorzugt werden, da

  +Select [list@item]

eventuell nur das Element markiert, nicht jedoch die entsprechende Aktion auslöst. (Ein Beispiel hierfür ist die Schriftartenauswahl bei Notepad.)

Die formale Unterstützung eines Patterns bedeutet leider noch lange nicht, dass der Aufruf des entsprechenden Auswahl-Events irgendeine Wirkung zeigt. Dies ist zum Beispiel in der Rechner-Applikation von Windows der Fall, wenn man zu einem (nicht sichtbaren) Eintrag der Modus-Auswahlliste blättern möchte (ScrollItem pattern). Um dieses Problem zu umgehen, kann in diesem Fall ein select abgespielt werden, unabhängig davon, ob der Eintrag gerade sichtbar ist.

Weil das "weiche" Abspielen von Aktionen häufig im provider nicht implementiert ist funktionieren diese Spezialaktionen nur bedingt.

Bei 'Tastaturevents' kann ein Text nur dann direkt über einen 'Texteingabe' Knoten gesetzt werden, wenn das Value pattern unterstützt wird. Ansonsten muss der Text über einzelne Tastaturevents eingegeben werden.

Skripting

Intern stellt die win Engine ein UI Automation Element mit der Klasse WinControl dar. Um auf ein Element in einem Groovy 'SUT-Skript' Knoten zuzugreifen, führen Sie folgendes Skript mit der passenden 'QF-Test ID der Komponente' aus:

def winc = rc.getComponent("myComponentID")
println winc
Beispiel 15.1:  Zugriff auf ein WinControl in einem Groovy 'SUT-Skript'

Die Methoden der Klasse WinControl sind in Abschnitt 52.13.1 detailliert beschrieben:

  • getUiaType(), getUiaClassName(), getFramework(), getUiaName(), getUiaId(), getUiaDescription(), getUiaHelp(), getHwnd(), getLocation(), getSize(), getLocationOnScreen(), getPatterns(), hasPattern() um die UI Automation Eigenschaften eines Elements zu erhalten
  • getChildren(), getParent(), getChildrenOfType(), getAncestorOfType(), getElementsByClassName() für die Elementhierarchie
  • getUiaControl() um ein AutomationBase zu erhalten, welches dann mit der uiauto-Skriptbibliothek verwendet werden kann (Kapitel 50).

Optionen

Das Verhalten der win Engine kann über die QF-Test Optionen beeinflusst werden. Darüber hinaus können noch Properties gesetzt werden, die den nativen Teil des UI Automation Clients beeinflussen. Diese Optionen und Properties können in einem 'SUT-Skript' Knoten gesetzt werden via:

  rc.setOption(<name>, <value>)

bzw.

  rc.engine.preferences().setPref(<name>, <value>)

Um die gesetzte Option zurückzusetzen genügt:

  rc.unsetOption(<name>)

Windows Skalierung

Auf Grund stetig wachsender Bildschirmauflösungen in den letzten Jahren gibt es in Windows die Möglichkeit die Skalierungseinstellungen anzupassen. Windows-Anwendungen sowie ihre Komponenten und die darin dargestellte Schrift werden an diesen Skalierungsfaktor angepasst. UWP, WPF und Windows-Forms-Anwendungen skalieren normalerweise automatisch aber Win32-Anwendungen und deren Steuerelemente im Besonderen behalten teilweise ihre Größe oder skalieren auf andere Weise.

QF-Test arbeitet standardmäßig mit physischen Bildschirmkoordinaten. Angenommen die Skalierung ist auf 125% gesetzt und eine Schaltfläche würde bei 100% Skalierung an der Position (24,40) mit einer Größe von (100,20) existieren, so wäre diese bei dieser Skalierung an Position (30,50) und hätte eine Größe von (125,25). Daraus ergeben sich folgende Konsequenzen:

  • unterschiedliche Geometrie wenn die Komponente erneut aufgenommen wird
  • Unterschiede bei der Geometrie, wenn QF-Test versucht eine Komponente zu identifizieren, die mit 100% Skalierung aufgenommen wurde.
  • Ein (harter) Mauklick auf einen bestimmten Bereich innerhalb eines Elementes kann fehlschlagen, weil der skalierte Bereich weiter von der oberen-rechten Ecke des Elementes entfernt ist.

Damit QF-Test mit logischen anstelle von physischen Koordinaten arbeitet, kann Options.OPT_WIN_USE_SCALING auf true gesetzt werden. QF-Test verwendet dann den Skalierungsfaktor des primären Monitors um die Geometrie für Komponenten und die Koordinaten für Maus-Events anzupassen. Bei dieser Anpassung kann es je nach eingestelltem Skalierungsfaktor zu Rundungsfehlern kommen, wenn die Koordinaten neu berechnet werden, da diese als Integerwerte gespeichert sind. Das kann dazu führen, dass Koordinaten um 1 Pixel abweichen.

Sichtbarkeit

Es kann vorkommen, dass ein Ereignis auf eine Komponente ausgelöst werden soll, die gerade nicht sichtbar ist (da sie gerade außerhalb des sichtbaren Bereiches gescrollt ist). Um auf diese Komponente ein invoke Event abzuspielen, muss vorher die Prüfung auf Sichtbarkeit deaktiviert werden, die normalerweise ein Bestandteil der Objekterkennung ist.

Das kann durch das Setzen von Options.OPT_WIN_TEST_VISIBILITY auf false erreicht werden. Nach der Wiedergabe des jeweiligen Events sollte die Sichtbarkeitsprüfung wieder aktiviert werden.

Verbinden zu einem Fenster einer bestimmten Klasse

Wenn eine Anwendung via -class <class name> verbunden wird, ignoriert QF-Test standardmäßig alle Haupt-Fenster der Anwendung, die nicht dieser Klasse entsprechen. Auf diesem Weg kann man QF-Test zum Beispiel lediglich mit der Windows Taskbar verbinden und den Desktop und die darauf liegenden Icons komplett ignorieren, obwohl sie im gleichen Prozess laufen.

Um dennoch alle Haupt-Fenster (toplevels) eines Prozesses zugreifbar zu machen, kann die Präferenz "windriver.restrict.tops.to.class" auf "false" gesetzt werden.

Begrenzung der Anzahl von Kind-Elementen

Große Hierarchien von UI Automation Elementen können Aufnahme und Wiedergabe deutlich verlangsamen. Um dem entgegenzuwirken, begrenzt QF-Test die Anzahl der Kind-Elemente, wenn diese vom Client abgerufen werden.

Der vorgegebene Wert beträgt 100 und kann über Options.OPT_WIN_MAX_CHILDREN angepasst werden.

(Aktuelle) Einschränkungen

Die aktuelle Implementierung des Windows-Testens enthält noch eine Reihe von Einschränkungen. Wir werden versuchen, die Funktionalität laufend zu verbessern, doch mag die eine oder andere Einschränkung noch eine Weile bestehen.

Da die Unterstützung der UI Automation vom Framework abhängt, mit dem die Anwendung entwickelt wurde, ist die Aufnahme in QF-Test eventuell nicht konsistent. Zum Beispiel kann beim Öffnen eines Dialogs ein 'Warten auf Komponente' aufgezeichnet werden oder auch nicht.

Das Testen von Anwendungen, die aus mehreren Prozessen bestehen, ist komplex und erfordert mehrere win Clients.

Weitere Einschränkungen und noch nicht implementierte Funktionalitäten (Stand Januar 2020) sind unter anderem:

  • Die unterstützten Check-Arten sind so gut wie vollständig. Es fehlen aber noch einige speziellere Checks. Dies sollen in einer zukünftigen QF-Test Version vervollständigt werden.
  • Elemente einer Titelleiste einer Windows App können nicht (einfach) angesprochen werden, weil diese in einem anderen Prozess liegen. Dies könnte in einer zukünftigen QF-Test Version behoben werden.
  • Die Event-Weiterleitung vom Textelement einer Schaltfläche auf das Schaltflächenelement selbst erfolgt bei der Aufnahme eines Mausklicks, kann aber an anderer Stelle fehlen. Dies sollte in einer zukünftigen QF-Test Version behoben sein.

Links

Das Windows Automation API ist beschrieben unter: https://docs.microsoft.com/en-US/windows/desktop/WinAuto/windows-automation-api-portal.

Weitere Informationen zu Mark Humphreys ui-automation Java-Bibliothek finden Sie unter https://github.com/mmarquee.