Im Blogbeitrag zum Testen von Windows Store-Apps wurde hauptsächlich darauf eingegangen, worauf die Apps getestet werden sollten. Sie können die im vorigen Beitrag besprochenen Prüfbereiche zwar manuell ausführen, es ist jedoch effizienter, einige dieser Prüfbereiche zu automatisieren. Eine automatisierte Überprüfung Ihrer App bietet viele Vorteile. Durch das automatisierte Testen sparen Sie im Vergleich zu manuellen Tests Zeit und Geld. Nach dem Erstellen können die automatisierten Tests wiederholt zu minimalen Kosten und bedeutend schneller als manuelle Tests ausgeführt werden. So wird kostengünstig die hohe Qualität jeder neuen Version Ihrer App sichergestellt. Automatisierte Tests verbessern zudem die Genauigkeit der Überprüfung, da selbst dem gewissenhaftesten Tester bei langwierigen manuellen Tests Fehler unterlaufen.

In diesem Beitrag finden Sie einige Tipps und Methoden zur Automatisierung von Tests für Windows 8-Apps. Beachten Sie, dass es sich bei automatisierten Tests um eine leistungsstarke Methode handelt, die vorab einen gewissen Aufwand erfordert, wenn sie umfassend genutzt werden soll. Die Tipps und Beispiele in diesem Beitrag sollen Ihnen bei den ersten Schritten helfen. Anschließend müssen Sie auf dieser Grundlage jedoch eine eigene Infrastruktur aufbauen. Wenn Sie an weniger umfangreichen Testmethoden interessiert sind, lesen Sie den aktuellen Blogbeitrag zum Testen von Apps mit Visual Studio.

Ein typischer Automatisierungsworkflow für das Testen von Apps umfasst die folgenden Schritte:

  • Installation: Automatisieren der Installation Ihrer App
  • Aktivierung: Automatisieren der Aktivierung Ihrer App
  • Laufzeit: Automatisieren der Ausführung Ihrer App
  • Lebenszyklusstatus: Automatisieren des Anhaltens, Fortsetzens und Beendens Ihrer App
  • Deinstallation: Automatisieren der Deinstallation Ihrer App

Betrachten wir nun die einzelnen Schritte und die entsprechenden Automatisierungstools/-technologien genauer.

Hinweis zu Tests unter Windows RT

Bevor wir uns intensiver mit der Automatisierung befassen, hier ein kurzer Hinweis zum Testen unter Windows RT: x86/64-Prozesse können nicht für die Ausführung unter Windows RT erstellt oder portiert werden. Daher beziehen sich die in diesem Beitrag erläuterten Tools und Technologien nicht auf Tests unter Windows RT. Es wird empfohlen, für Tests unter Windows RT Visual Studio zu verwenden.

Automatisieren der Installation Ihrer App

Um die App testen zu können, müssen Sie diese zunächst auf Ihrem Testcomputer installieren. Es wird empfohlen, mithilfe von Visual Studio ein App-Paket lokal freizugeben, um ein App-Paket zu erstellen und auf dem Testcomputer zu installieren. Mit dieser Option wird in Visual Studio ein Ordner erstellt, der alle relevanten Dateien sowie ein PowerShell-Skript enthält, mit dem das entsprechende Zertifikat, die Lizenz, die Abhängigkeitspakete und das App-Paket selbst installiert werden. Die App muss manuell paketiert werden, die Installation beruht jedoch auf PowerShell und kann automatisiert werden. Im Folgenden werden die Installationsschritte ausgeführt.

Schritt 1:

Aktivieren Sie die PowerShell-Skriptausführung. Aus Sicherheitsgründen beschränkt die PowerShell-Standardausführungsrichtlinie die Ausführung von PowerShell-Skripts. Daher muss diese Richtlinie überschrieben werden. Dieser Schritt erfolgt manuell, da er eine Benutzerinteraktion erfordert. Glücklicherweise muss er nur einmal pro Computer ausgeführt werden. Führen Sie diesen Befehl von einem PowerShell-Fenster mit erhöhten Rechten aus, um die PowerShell-Skriptausführung zu starten.

PS C:\> Set-ExecutionPolicy AllSigned
 Powershell_admin
Abbildung 1: Aktivieren der PowerShell-Skriptausführung

Schritt 2:

Kopieren Sie den in Visual Studio erstellten Ordner mit dem App-Paket auf den Testcomputer, und führen Sie das PowerShell-Skript „Add-AppDevPackage“ in einem PowerShell-Fenster aus. Verwenden Sie diesen Befehl:

PS C:\JSGrid1_1.0.0.0_AnyCPU_Debug_Test> .\Add-AppDevPackage.ps1
Windows PowerShell
Abbildung 2: Ausführen des Add-AppDevPackage-Skripts

Schritt 3:

Erwerben Sie eine Entwicklerlizenz. Dieser Schritt erfolgt manuell, da er eine Benutzerinteraktion erfordert. Dies muss innerhalb des Gültigkeitszeitraums der Lizenz einmal pro Computer ausgeführt werden. Wenn Ihr Testcomputer bereits über eine Entwicklerlizenz verfügt, können Sie diesen Schritt überspringen.

Akzeptieren Sie die UAC-Aufforderung, und befolgen Sie die Anweisungen zum Erwerben einer Entwicklerlizenz. In den folgenden Screenshots wird die Anzeige dargestellt.

Im ersten Screenshot muss den Lizenzvereinbarungen für das Installieren einer Entwicklerlizenz zugestimmt werden. Klicken Sie auf Ich stimme zu, wenn Sie fortfahren möchten.

Powershell_devlic

Abbildung 3: Akzeptieren der Aufforderung zum Erwerb der Entwicklerlizenz

Geben Sie im Dialogfeld Microsoft-Konto die Angaben für Ihr Microsoft-Konto ein. Wenn Sie nicht über ein Microsoft-Konto verfügen, klicken Sie auf Anmelden, um ein Konto zu erstellen.

msaccount_signin

Abbildung 4: Anmelden mit den Anmeldeinformationen des Microsoft-Kontos

Eine Bestätigung der Erstellung Ihrer Entwicklerlizenz und deren Ablaufdatum werden angezeigt.

devlic_approve

Abbildung 5: Erfolgreicher Erwerb einer Entwicklerlizenz

Im nächsten Screenshot wird angezeigt, dass Sie über eine Entwicklerlizenz verfügen, und dass das Paket erfolgreich installiert wurde.

PS_packagesuccess

Abbildung 6: Installation abgeschlossen

Automatisieren der Aktivierung Ihrer App

Ihr App-Paket wurde nun auf dem Testcomputer installiert, und Sie können die App starten. Sie können die Aktivierung Ihrer App mithilfe der Schnittstelle IApplicationActivationManager automatisieren. Diese API ist als Teil des Windows SDKs verfügbar, das in der Standardeinstellung mit Visual Studio 2012 installiert wird. Starten Sie die App mithilfe der Methode IApplicationActivationManager::ActivateApplication. Der folgende Codeausschnitt erläutert die Verwendung dieser Methode.

#include "stdafx.h"
#include <shlobj.h>
#include <stdio.h>
#include <shobjidl.h>
#include <objbase.h>
#include <atlbase.h>
#include <string>

/*++

Routine Description:

This routine launches your app using IApplicationActivationManager.

Arguments:

strAppUserModelID - AppUserModelID of the app to launch.
pdwProcessId - Output argument that receives the process id of the launched app.

Return value:

HRESULT indicating success/failure

--*/
HRESULT LaunchApp(const std::wstring& strAppUserModelId, PDWORD pdwProcessId)
{
CComPtr<IApplicationActivationManager> spAppActivationManager;
HRESULT hrResult = E_INVALIDARG;
if (!strAppUserModelId.empty())
{
// Instantiate IApplicationActivationManager
hrResult = CoCreateInstance(CLSID_ApplicationActivationManager, NULL, CLSCTX_LOCAL_SERVER, IID_IApplicationActivationManager, (LPVOID*)&spAppActivationManager);

if (SUCCEEDED(hrResult))
{
// This call ensures that the app is launched as the foreground window
hrResult = CoAllowSetForegroundWindow(spAppActivationManager, NULL);

// Launch the app
if (SUCCEEDED(hrResult))
{
hrResult = spAppActivationManager->ActivateApplication(strAppUserModelId.c_str(), NULL, AO_NONE, pdwProcessId);
}
}
}

return hrResult;
}

int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hrResult = S_OK;
if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))
{
if (argc == 2)
{
DWORD dwProcessId = 0;
++argv;
hrResult = LaunchApp(*argv, &dwProcessId);
}
else
{
hrResult = E_INVALIDARG;
}

CoUninitialize();
}

return hrResult;
}

 

Sie können diesen Ausschnitt kompilieren, um ihn folgendermaßen zu verwenden:

C:\>Win8AppLaunch.exe Microsoft.BingNews_8wekyb3d8bbwe!AppexNews

In diesem Codeausschnitt ist der Aufruf an CoAllowSetForegroundWindow von entscheidender Bedeutung. Ohne diesen Aufruf wird die App zwar gestartet, sie wird jedoch nicht in den Vordergrund gebracht. Aufgrund dessen wurde häufig versucht, ein Starttool zu schreiben.

Abschließend ein kurzer Hinweis zu „AppUserModelId“: Bei diesem Ansatz ist für das Starten Ihrer App die „AppUserModelId“ der App erforderlich. Die „AppUserModelId“ fungiert als eindeutige ID der App. Es wird empfohlen, diese mit PowerShell abzurufen. Im Folgenden finden Sie ein PowerShell-Skript, mit dem erläutert wird, wie Sie die „AppUserModelId“ für alle auf dem Computer installierten Apps abrufen können.

$installedapps = get-AppxPackage
foreach ($app in $installedapps)
{
foreach ($id in (Get-AppxPackageManifest $app).package.applications.application.id)
{
$app.packagefamilyname + "!" + $id
}
}

Zudem können Sie mithilfe von IAppxManifestReader die Apps im Paket nummerieren und die „AppUserModelId“ mithilfe der Methode IAppxManifestApplication::GetAppUserModelId abrufen. Wenn Sie jedoch in erster Linie eine bestimmte App testen möchten, ist das Verwenden dieser Registrierung bedeutend einfacher, als ein Tool zu schreiben, das das App-Manifest liest.

Automatisieren der Kernfunktionen Ihrer App

Ihre App wurde nun auf dem Testcomputer installiert und kann über die Automatisierung gestartet werden. Im nächsten Schritt wird das Testen der Kernfunktionen der App automatisiert. Dies kann durch eine Kombination aus Modultests und einer Automatisierung der App über deren Benutzeroberfläche mithilfe einer Benutzeroberflächenautomatisierung erfolgen.

Die Modultests und Benutzeroberflächenautomatisierung sind sich ergänzende Methoden. Bei gemeinsamer Verwendung können Sie mit diesen Methoden eine umfassend getestete App mit höherer Qualität erzielen. Mithilfe von Modultests können Sie die Kernfunktionslogik Ihrer App automatisieren. Ein über die Benutzeroberfläche automatisiertes Testen ermöglicht das Prüfen der App-Funktionen, indem die Verwendung der Benutzeroberfläche simuliert wird. Mithilfe einer Kombination dieser Ansätze können Sie Ihre App umfassender testen.

Betrachten wir nun einige der Tools und Methoden für die einzelnen Ansätze.

Modultests

Modultests eignen sich hervorragend dazu, die Kernfunktionen Ihrer App zu überprüfen. Visual Studio 2012 unterstützt das Erstellen von Modultests für in C# oder C++ geschriebene Apps. Weitere Informationen zum Erstellen und Ausführen von Modultests in Visual Studio 2012 finden Sie unter Erstellen und Ausführen von Modultests. Wenn Sie bereits mit anderen Testframeworks vertraut sind, können Sie auch diese weiterhin für Modultests für Windows Store-Apps verwenden.

Automatisierung der Benutzeroberfläche

Modultests können für das Testen der inneren Abläufe einer App hilfreich sein, die Benutzeroberfläche Ihrer App wird jedoch nicht mit einbezogen. Wir empfehlen eine Benutzeroberflächenautomatisierung (UIA), um die Funktionen der Benutzeroberfläche einer App zu überprüfen.

Im Windows 8-Sicherheitsmodell verfügen Apps nicht über die für einen Benutzeroberflächen-Automatisierungsclient erforderlichen Berechtigungen. Sie können jedoch eine Desktop-App schreiben, die als Automatisierungsclient mit der App als Ziel fungiert. Hierzu muss Ihre Automatisierungsclient-Desktop-App mit UIAccess-Berechtigungen erstellt werden (siehe unter Automatisierung der Benutzeroberfläche – Sicherheitsübersicht.

Das Windows SDK beinhaltet einige Tools, die als gute Beispiele für Benutzeroberflächen-Automatisierungsclients verwendet werden können: „Inspect.exe“ und „AccEvent.exe“. Mit „Inspect.exe“ können Sie die Benutzeroberflächen-Automatisierungsstruktur beider Arten von Apps prüfen. Mit „AccEvent“ wird nach UIA-Ereignissen gelauscht. Auf einem Computer, auf dem das Windows SDK installiert wurde, finden Sie diese Tools in der Regel unter „%Programme(x86)%\Windows Kits\8.0\bin\<Architektur>“. Im Folgenden sehen Sie beide Tools in Aktion.

inspect.exe

Abbildung 7: „Inspect“-Tool wird für die Bing News-App ausgeführt.

accevent_tool

Abbildung 8: „AccEvent“-Tool wird für die Bing Sports-App ausgeführt.

Sie können die UIA ähnlich wie bei dem von den beiden Tools verwendetem Ansatz einsetzen, um eine Desktopclient-App zu erstellen, mit der Ihre App automatisiert wird. Im Blogbeitrag Erstellen von Clientanwendungen für die Automatisierung der Benutzeroberfläche in C++ und C# finden Sie äußerst hilfreiche erste Informationen zum Erstellen eines UIA-Clients. In diesem Blogbeitrag wird die herkömmliche Benutzeroberflächenautomatisierung erläutert. Dieselben Methoden können jedoch für beliebige Apps verwendet werden.

Das Beispiel „UI Automation Document Content Client“ verdeutlicht, wie die UIA-Steuerelementmuster zum Abrufen verschiedener Inhaltstypen aus dem Fenster der Ziel-App verwendet werden können, z. B. Header, Kommentare oder die aktuelle Auswahl. Das Beispiel „Touch Injection“ verdeutlicht, wie die Fingereingabeeinfügungs-APIs beim Prüfen Ihrer App zum Simulieren einer Fingereingabe verwendet werden können.

Wie bereits erwähnt, handelt es sich bei den Modultests und der Benutzeroberflächenautomatisierung um sich ergänzende Methoden, mit denen sowohl die Kernfunktionslogik der App als auch deren Benutzeroberflächenfunktionen automatisiert werden können. Debuggen Sie Ihre App mithilfe dieser Methoden.

Automatisieren des Lebenszyklusstatus Ihrer App

Wie im Blogbeitrag Lebenszyklusverwaltung und dynamische Apps erläutert, kann bei Apps ein Übergang zwischen verschiedenen Laufzeitstatus erfolgen. Für Ihre Tests ist es wichtig, die App in all diesen Zuständen zu prüfen. Das Automatisieren des Übergangs in diese Zustände ist mithilfe eines Tools (PLMDebug) möglich, das Teil der Debugging-Tools für Windows ist. Mit diesem Befehlszeilentool können Sie direkt den Übergang Ihrer App in verschiedene Lebenszykluszustände automatisieren.

Wenn PLMDebug für Ihre Anforderungen nicht ausreicht, können Sie mithilfe der Schnittstelle IPackageDebugSettings ein eigenes Tool implementieren, mit dem der Lebenszyklusstatus Ihrer App geändert wird. Diese API ist als Teil des Windows SDKs verfügbar, das in der Standardeinstellung mit Visual Studio installiert wird. Der Code verdeutlicht, wie mithilfe der IPackageDebugSettings-API der Lebenszyklusstatus der App geändert wird, um sicherzustellen, dass Ihre App bei diesen Statusübergängen ordnungsgemäß funktioniert.

#include "stdafx.h"
#include <stdio.h>
#include <shobjidl.h>
#include <objbase.h>
#include <atlbase.h>
#include <string>

/*++

Routine Description:

This routine changes the lifecycle state of a Windows Store app depending on the input argument.

Arguments:

strPackageFullName - Package Full Name of the Windows Store app
strOperation - Operation to take (/enabledebug, /suspend, /resume, /terminate, /cleanTerminate, /disabledebug)

Return Value:

HRESULT indicating success/failure

--*/
HRESULT ChangeLifecycleState(const std::wstring& strPackageFullName, const std::wstring& strOperation)
{
CComPtr<IPackageDebugSettings> spPackageDebugSettings;
HRESULT hrResult = E_INVALIDARG;

if (!strPackageFullName.empty() && !strOperation.empty())
{
// Instantiate IPackageDebugSettings
hrResult = CoCreateInstance(CLSID_PackageDebugSettings, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&spPackageDebugSettings));

// Depending on the operation specified as the command line arg, change the lifecycle state of the app
if (SUCCEEDED(hrResult))
{
if (_wcsicmp(strOperation.c_str(), L"/enableDebug") == 0)
{
// Increment debug ref count on the app package - you must do this before you can suspend/resume/terminate
hrResult = spPackageDebugSettings->EnableDebugging(strPackageFullName.c_str(), NULL, NULL);
}
else if (_wcsicmp(strOperation.c_str(), L"/suspend") == 0)
{
// Asynchronously suspend the app
hrResult = spPackageDebugSettings->Suspend(strPackageFullName.c_str());
}
else if (_wcsicmp(strOperation.c_str(), L"/resume") == 0)
{
// Resume the app
hrResult = spPackageDebugSettings->Resume(strPackageFullName.c_str());
}
else if (_wcsicmp(strOperation.c_str(), L"/terminate") == 0)
{
// Terminate the app
hrResult = spPackageDebugSettings->TerminateAllProcesses(strPackageFullName.c_str());
}
else if (_wcsicmp(strOperation.c_str(), L"/cleanTerminate") == 0)
{
// Clean terminate the app - suspend, then terminate
hrResult = spPackageDebugSettings->StartServicing(strPackageFullName.c_str());
if (SUCCEEDED(hrResult))
{
hrResult = spPackageDebugSettings->StopServicing(strPackageFullName.c_str());
}
}
else if (_wcsicmp(strOperation.c_str(), L"/disableDebug") == 0)
{
// Decrement debug ref count on the app package
hrResult = spPackageDebugSettings->DisableDebugging(strPackageFullName.c_str());
}
else
{
hrResult = E_INVALIDARG;
}
}
}

return hrResult;
}

int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hrResult = S_OK;
if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))
{
if (argc == 3)
{
std::wstring strOperation(argv[1]);
std::wstring strPackageFullName(argv[2]);
hrResult = ChangeLifecycleState(strPackageFullName, strOperation);
}
else
{
hrResult = E_INVALIDARG;
}

CoUninitialize();
}

return hrResult;
}

 

Wenn Sie diesen Codeausschnitt als „LifecycleManager.exe“ kompilieren, können Sie ihn folgendermaßen verwenden.
C:\>Win8AppLifecycleManager.exe /enableDebug Microsoft.BingNews_1.2.0.98_x64__8wekyb3d8bbwe

C:\> Win8AppLifecycleManager.exe /suspend Microsoft.BingNews_1.2.0.98_x64__8wekyb3d8bbwe

C:\> Win8AppLifecycleManager.exe /resume Microsoft.BingNews_1.2.0.98_x64__8wekyb3d8bbwe

C:\> Win8AppLifecycleManager.exe /terminate Microsoft.BingNews_1.2.0.98_x64__8wekyb3d8bbwe

C:\> Win8AppLifecycleManager.exe /cleanTerminate Microsoft.BingNews_1.2.0.98_x64__8wekyb3d8bbwe

C:\> Win8AppLifecycleManager.exe /disableDebug Microsoft.BingNews_1.2.0.98_x64__8wekyb3d8bbwe
 

Abschließend ein kurzer Hinweis zu „PackageFullName“: Alle hier behandelten Ansätze für das Verwalten des Lebenszyklusstatus erfordern „PackageFullName“ als Eingabeargument, anhand dessen die App erkannt wird. Zum Abrufen von „PackageFullName“ wird das PowerShell-Cmdlet Get-AppxPackage empfohlen. Dies wird im nächsten Beispiel deutlich (Ausgabe zur Verbesserung der Lesbarkeit gekürzt).

PS C:\> Get-AppxPackage

Name : Microsoft.BingNews
Publisher : CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
Architecture : X64
ResourceId :
Version : 1.2.0.98
PackageFullName : Microsoft.BingNews_1.2.0.98_x64__8wekyb3d8bbwe ←
InstallLocation : C:\Program Files\WindowsApps\Microsoft.BingNews_1.2.0.98_x64__8wekyb3d8bbwe
IsFramework : False
PackageFamilyName : Microsoft.BingNews_8wekyb3d8bbwe
PublisherId : 8wekyb3d8bbwe

Automatisieren der Deinstallation Ihrer App

Zum Deinstallieren der App werden PowerShell-Cmdlets empfohlen, insbesondere Remove-AppxPackage. Im Folgenden finden Sie ein Beispiel (Ausgabe zur Verbesserung der Lesbarkeit gekürzt).

PS C:\> Get-AppxPackage

Name : Microsoft.SDKSamples.ListViewEssentials.JS
Publisher : CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
Architecture : Neutral
ResourceId :
Version : 1.0.0.0
PackageFullName : Microsoft.SDKSamples.ListViewEssentials.JS_1.0.0.0_neutral__8wekyb3d8bbwe ←
InstallLocation : C:\Users\user1\Downloads\Samples\Controls_ListViewBasic\JS\bin\Debug\AppX
IsFramework : False
PackageFamilyName : Microsoft.SDKSamples.ListViewEssentials.JS_8wekyb3d8bbwe
PublisherId : 8wekyb3d8bbwe

PS C:\> Remove-AppxPackage Microsoft.SDKSamples.ListViewEssentials.JS_1.0.0.0_neutral__8wekyb3d8bbwe

Fazit

In diesem Blogbeitrag wurden eine Reihe von Tipps, Tools und Methoden zum Automatisieren der Tests für Ihre Apps vorgestellt. Automatisierte Tests können eine kostengünstige Möglichkeit sein, um die Überprüfung Ihrer Apps zu verbessern, und sicherzustellen, dass die Qualität stets hoch bleibt. Hierbei muss beachtet werden, dass manuelle Tests bei der Prüfung ebenfalls eine wichtige Rolle spielen. Sie fügen der App-Überprüfung den Faktor Mensch hinzu. Daher ist eine Kombination aus automatisierten und manuellen Tests ein umfassender Ansatz für das Testen von Apps.

– Ashwin Needamangala, Principal Test Lead, Windows

Besonderen Dank an Mete Goktepe, J. Kalyana Sundaram, Ben Betz, Will Wei, Chris Edmonds, Craig Campbell und Jake Sabulsky für ihre Hilfe und ihren Anteil an diesem Blogbeitrag.