Dans le billet de blog consacré au test des applications du Windows Store, nous avons principalement indiqué pourquoi tester les applications. Bien qu'il soit possible d'exécuter manuellement les vérifications que nous avons abordées dans le billet précédent, il est plus efficace d'automatiser certains de ces tests. L'automatisation de la vérification de votre application présente plusieurs avantages. Les tests automatisés permettent de gagner du temps et de l'argent, que vous devriez sinon consacrer aux tests manuels. Une fois créés, les tests automatisés peuvent être exécutés à maintes reprises pour un coût minimal et beaucoup plus rapidement que les tests manuels. Vous pouvez ainsi vous assurer que la qualité de votre application demeure élevée et que le coût reste faible à chaque nouvelle version de l'application. Les tests automatisés améliorent par ailleurs la précision de la vérification, car même le testeur le plus consciencieux n'est pas à l'abri d'erreurs lorsqu'il effectue des tests manuels fastidieux.

Dans ce billet, nous proposons certains conseils et techniques pour automatiser le test des applications Windows 8. N'oubliez pas que les tests automatisés font appel à une technique puissante et qu'ils requièrent un certain investissement initial dont vous recueillerez tout le bénéfice par la suite. Les conseils et exemples donnés dans ce billet ont pour objectif de vous aider à démarrer, mais vous devrez ensuite créer et gérer votre propre infrastructure. Si vous recherchez des techniques de test moins lourdes, consultez le récent blog expliquant comment tester des applications avec Visual Studio.

Le processus de test classique des applications se compose des étapes suivantes :

  • Installation : automatisez l'installation de votre application.
  • Activation : automatisez l'activation de votre application.
  • Exécution : automatisez votre application lorsqu'elle est en cours d'exécution.
  • États du cycle de vie : automatisez la suspension, la reprise et l'arrêt de votre application.
  • Désinstallation : automatisez la désinstallation de votre application.

Examinons chacune de ces étapes en détail, ainsi que les technologies/outils d'automatisation à utiliser pour chacune d'elles.

Remarque concernant les tests sur Windows RT

Avant d'aborder l'automatisation, il convient de noter ce qui suit concernant les tests sur Windows RT. Vous ne pouvez pas créer ou porter de processus x86/64 pour qu'ils s'exécutent sur Windows RT. Par conséquent, tous les outils et technologies abordés dans le reste de ce billet ne s'appliquent pas aux tests sur Windows RT. Nous vous recommandons d'utiliser Visual Studio pour les tests sur Windows RT.

Automatisation de l'installation de votre application

Pour tester votre application, vous devez d'abord l'installer sur votre machine de test. L'utilisation de Visual Studio pour partager un package de l'application localement est la méthode recommandée pour créer votre package de l'application et pour l'installer sur la machine de test. Dans ce cas, Visual Studio crée un dossier qui contient tous les fichiers appropriés, ainsi qu'un script PowerShell qui installe le certificat et la licence qui conviennent, les packages dépendants et le package de l'application même. Vous devez empaqueter votre application manuellement, mais l'installation est basée sur PowerShell et peut être automatisée. L'installation se déroule comme suit.

Étape 1 :

Autorisez l'exécution du script PowerShell. Pour des raisons de sécurité, la stratégie d'exécution par défaut de PowerShell limite l'exécution des scripts PowerShell, vous devez donc remplacer cette stratégie. Cette étape est manuelle, car elle requiert l'interaction de l'utilisateur. Heureusement, vous ne devez le faire qu'une seule fois par machine. Exécutez cette commande dans une fenêtre PowerShell avec élévation de privilèges pour autoriser l'exécution du script PowerShell.

PS C:\> Set-ExecutionPolicy AllSigned
 Powershell_admin
Figure 1 : autoriser l'exécution du script PowerShell

Étape 2 :

Copiez le dossier du package de l'application créé par Visual Studio sur la machine de test et exécutez le script PowerShell Add-AppDevPackage depuis une fenêtre PowerShell. Utilisez cette commande :

PS C:\JSGrid1_1.0.0.0_AnyCPU_Debug_Test> .\Add-AppDevPackage.ps1
Windows Powershell
Figure 2 : exécuter le script Add-AppDevPackage

Étape 3 :

Procurez-vous une licence de développeur. Cette étape est manuelle, car elle requiert l'interaction de l'utilisateur. Vous ne devez cependant l'effectuer qu'une seule fois par machine pour la période de validité de la licence. Si la machine de test possède déjà la licence de développeur, vous pouvez ignorer cette étape.

Acceptez l'invite Contrôle de compte d’utilisateur et suivez les instructions permettant d'obtenir une licence de développeur. Les captures d'écran ci-dessous illustrent ce que vous verrez.

Dans cette première capture d'écran, vous devez accepter le contrat de licence pour installer une licence de développeur. Cliquez sur [I Agree] (J'accepte) pour continuer.

Powershell_devlic

Figure 3 : accepter l'invite d'acquisition de la licence de développeur

Dans la boîte de dialogue [Microsoft account] (Compte Microsoft), entrez votre compte Microsoft. Si vous ne possédez pas de compte Microsoft, cliquez sur [Sign up] (S'inscrire) pour en créer un.

msaccount_signin

Figure 4 : se connecter avec les informations d'identification du compte Microsoft

Vous recevez une confirmation indiquant que votre licence de développeur a été créée, ainsi que sa date d'expiration.

devlic_approve

Figure 5 : licence de développeur acquise

La capture d'écran suivante indique que vous avez obtenu votre licence de développeur et que votre package a été installé.

PS_packagesuccess

Figure 6 : installation terminée

Automatisation de l'activation de votre application

Votre package de l'application est maintenant installé sur la machine de test et vous êtes prêt à lancer l'application. Vous pouvez automatiser l'activation de votre application avec l'interface IApplicationActivationManager. Cette API est disponible avec le SDK Windows qui est installé par défaut avec Visual Studio 2012. Utilisez la méthode IApplicationActivationManager::ActivateApplication pour lancer votre application. L'extrait de code ci-dessous illustre l'utilisation de cette méthode.

#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;
}

 

Vous pouvez compiler cet extrait de code et l'utiliser comme ceci :

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

Dans cet extrait de code, l'appel à la méthode CoAllowSetForegroundWindow est crucial. Sans cet appel, l'application est lancée, mais elle n'est pas affichée au premier plan. Un certain nombre de personnes ont déjà dû affronter ce problème en essayant d'écrire un outil de lancement.

Enfin, voici une remarque rapide au sujet d'AppUserModelId. Dans cette approche, pour lancer votre application, vous devez entrer l'AppUserModelId de votre application. L'AppUserModelId joue le rôle d'identifiant unique de votre application. Pour l'extraire, nous vous recommandons d'utiliser PowerShell. Voici un script PowerShell qui montre comment récupérer l'AppUserModelId de toutes les applications installées sur votre machine.

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

Vous pouvez également utiliser IAppxManifestReader pour énumérer les applications du package et obtenir l'AppUserModelId à l'aide de la méthode IAppxManifestApplication::GetAppUserModelId. Mais si vous voulez vous concentrer sur l'application que vous testez, il est beaucoup plus simple d'utiliser le Registre que d'écrire un outil qui lit le manifeste de votre application.

Automatisation des fonctionnalités principales de votre application

Votre application est maintenant installée sur la machine de test et votre automatisation est capable de la lancer. La prochaine étape consiste à automatiser les tests des fonctionnalités principales de votre application. Pour ce faire, vous pouvez associer les tests unitaires à l'automatisation de l'application via son interface utilisateur grâce à UI Automation.

Les tests unitaires et UI Automation sont des techniques complémentaires qui, utilisées ensemble, peuvent permettre d'obtenir une application d'excellente qualité et testée plus largement. Les tests unitaires vous permettent d'automatiser la logique métier principale inhérente à l'application. Les tests effectués avec UI Automation vous permettent de vérifier les fonctionnalités de votre application en simulant l'utilisation de son interface utilisateur. L'utilisation combinée de ces deux approches vous permet de tester plus largement votre application.

Examinons certains outils et techniques de chacune de ces approches.

Tests unitaires

Les tests unitaires sont une technique puissante de vérification des fonctionnalités principales de votre application. Visual Studio 2012 permet de créer des tests unitaires pour les applications écrites en C# ou C++. Pour plus d'informations sur la création et l'exécution de tests unitaires depuis Visual Studio 2012, reportez-vous à l'article Création et exécution de tests unitaires. Si vous connaissez bien d'autres infrastructures de tests unitaires, vous pouvez également continuer à les utiliser pour tester votre application du Windows Store.

UI Automation

Les tests unitaires peuvent être utiles pour tester le fonctionnement interne de votre application, mais ils ne portent pas sur l'interface utilisateur de l'application. Nous vous recommandons UI Automation (UIA) pour vérifier les fonctionnalités de votre application par le biais de son interface utilisateur.

Dans le modèle de sécurité de Windows 8, les applications ne disposent pas des privilèges requis pour être un client UI Automation. Vous pouvez toutefois écrire une application de bureau qui agit comme un client UI Automation avec votre application comme cible. Pour ce faire, votre application de bureau cliente UI Automation doit être créée avec des autorisations UIAccess, comme indiqué dans Vue d'ensemble de la sécurité UI Automation.

Le SDK Windows inclut des outils qui sont de bons exemples de clients UI Automation : Inspect.exe et AccEvent.exe. L'outil Inspect vous permet d'inspecter l'arborescence d'UI Automation des deux types d'applications. L'outil AccEvent écoute les événements UIA. Sur une machine sur laquelle le SDK Windows est installé, ces outils se trouvent généralement sous %ProgramFiles(x86)%\Windows Kits\8.0\bin\<architecture>. Voici les deux outils en pratique.

inspect.exe

Figure 7 : outil Inspect s'exécutant sur l'application Bing News

accevent_tool

Figure 8 : outil AccEvent s'exécutant sur l'application Bing Sports

Comme l'approche suivie par ces outils, vous pouvez utiliser UIA pour écrire une application de bureau cliente qui automatise votre application. Il est recommandé de lire le billet de blog sur la création d'applications clientes UI Automation en C++ et C# pour apprendre à créer un client UIA. Ce billet porte sur l'automatisation des interfaces utilisateur classiques, mais ces techniques sont valables pour n'importe quelle application.

L'exemple de client de contenu d'un document UI Automation explique comment utiliser les modèles de contrôle UIA pour extraire différents types de contenu dans la fenêtre de l'application cible (en-têtes, commentaires ou sélection courante). L'exemple d'injection tactile illustre comment utiliser les API d'injection tactile pour simuler le tactile afin de vérifier votre application.

Comme indiqué plus haut, les tests unitaires et UI Automation sont des techniques complémentaires qui vous permettent d'automatiser à la fois la logique métier principale inhérente à votre application et ses fonctionnalités lorsqu'elles sont testées depuis l'interface utilisateur. Utilisez ces deux techniques pour déboguer votre application.

Automatisation des états du cycle de vie de votre application

Comme nous l'avons vu dans le billet de blog Gestion du cycle de vie, une application peut passer par différents états d'exécution. Du point de vue des tests, il est important de vérifier votre application dans tous ces états. L'automatisation de la transition vers ces états est possible à l'aide d'un outil (PLMDebug) fourni avec les outils de débogage de Windows. Il s'agit d'un outil en ligne de commande prêt à l'emploi qui vous permet d'automatiser la transition de votre application d'un état du cycle de vie à un autre.

Si PLMDebug ne suffit pas pour répondre à vos besoins, vous pouvez utiliser l'interface IPackageDebugSettings pour implémenter votre propre outil capable de changer l'état du cycle de vie de votre application. Cette API est disponible avec le SDK Windows qui est installé par défaut avec Visual Studio. Le code illustre comment utiliser l'API IPackageDebugSettings pour changer l'état du cycle de vie de votre application afin de vérifier qu'elle fonctionne comme prévu lorsqu'elle change d'état.

#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;
}

 

Si vous compilez cet extrait de code en tant que LifecycleManager.exe, voici comment l'utiliser.
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
 

Enfin, voici une remarque rapide au sujet de PackageFullName. Toutes les approches que nous avons examinées pour gérer les états du cycle de vie nécessitent PackageFullName comme argument d'entrée permettant d'identifier l'application. Pour extraire PackageFullName, nous recommandons d'utiliser l'applet de commande PowerShell Get-AppxPackage, comme le montre l'exemple suivant (texte réduit pour améliorer la lisibilité).

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

Automatisation de la désinstallation de votre application

Pour désinstaller votre application, nous vous recommandons d'utiliser les applets de commande PowerShell et plus particulièrement Remove-AppxPackage. Voici un exemple (texte réduit pour améliorer la lisibilité).

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

Conclusion

Dans ce billet de blog, nous avons exposé plusieurs conseils, outils et techniques d'automatisation des tests de vos applications. Les tests automatisés peuvent constituer une solution économique pour améliorer le niveau de vérification de votre application et pour s'assurer que la qualité reste élevée. Cela étant dit, il est important de ne pas oublier que les tests manuels jouent également un rôle important dans la vérification. Ils apportent une intervention humaine dans le processus de vérification de votre application. Un mélange des tests automatisés et manuels vous permettra ainsi d'obtenir une approche complète des tests de votre application.

-- Ashwin Needamangala, chargé des tests, Windows

Je remercie tout particulièrement Mete Goktepe, J. Kalyana Sundaram, Ben Betz, Will Wei, Chris Edmonds, Craig Campbell et Jake Sabulsky pour leur aide et leur contribution à ce billet.