Automatiser les tests d’IHM avec UI Automation Framework
.jpg) | Par Frédéric QUEUDRET
CTO de la société Mpoware, accélérateur d’innovation. Société française d’édition de logiciels et de prestations de services sur la création d’outils de productivité pour les développeurs Visual Studio. http://www.mpoware.com/ |
Les tests de l’interface utilisateur ont toujours été un sujet difficile à adresser autrement que par les tests manuels utilisateurs. Dans cet article, nous allons montrer comment il est possible d’automatiser les tests d’IHM en .NET en utilisant le Microsoft UI AutomationFramework. Les techniques sont réutilisables quelle que soit la technologie de rendu (Win32, Windows Forms, WPF, …).
Les tests ont pris une part importante des projets informatiques car ils sont le garant de la qualité du logiciel produit et, dans les processus de test en continu, permettent de tester la non-régression induite par les nouveaux développements et de trouver les problèmes le plus tôt possible, ce qui minimise le coût de correction. Parmi les différentes techniques de tests, il en est une qui est difficile ou chère à mettre en place : le test des interfaces applicatives. Chère, car peu d’outils existent sur le marché, et difficile, car les outils existants ne supportent que quelques technologies d’interfaces graphiques ou utilisent des techniques de test qui les rendent trop sensibles aux changements et évolutions de l’IHM pendant les phases de développement.
Pourtant les tests d’Interface Homme-Machine – IHM - sont les seuls permettant de réellement tester l’application de bout-en-bout en simulant les actions de l’utilisateur. Le test d’IHM est une technique de « black-box testing » très utile pour les tests fonctionnels pour lesquels la connaissance interne du comportement ou de l’implémentation de l’objet testé n’est pas nécessaire. La plupart du temps, les tests IHM sont assimilés aux tests utilisateurs et l’application est validée par un ou plusieurs utilisateurs sur la base d’un cahier de tests regroupant l’ensemble des scénarii utilisateurs devant être joués, puis validés ou rejetés par l’utilisateur testeur. Etant donné le temps consommé par ce type de tests, ils ne sont effectués généralement qu’aux étapes importantes de livraison d’un projet et sur des applications nécessitant une très bonne qualité.
Dans cet article, nous allons présenter une technologie qui permet de simplifier les tests d’IHM et de les automatiser afin de pouvoir les rejouer plus souvent et ainsi améliorer la qualité des développements d’applications riches.
Introduction à Microsoft UI Automation
Microsoft UI Automation est une technologie disponible dans Windows XP, Vista, Windows Server 2003 et ultérieur, et utilisable par les développeurs .NET à partir du .NET framework 3.0. Microsoft UI Automation Framework est une API .NET permettant de naviguer dans les objets de l’interface, d’obtenir des informations ou d’exécuter des actions sur les contrôles graphiques. Successeur de Microsoft Active Accessibility (MSAA), UIAF permet aux utilisateurs ayant une accessibilité réduite de pouvoir utiliser l’outil informatique en ayant des solutions telles qu’un lecteur d’écran pour les malvoyants par exemple. Cette capacité technique le rend tout à fait intéressant dans le cadre des tests d’IHM puisqu’à la place d’un lecteur d’écran, nous pourrions imaginer un robot testeur d’IHM simulant les actions de l’utilisateur.
Le point fondamental de ce framework évolutif est qu’il n’est pas dépendant d’une technologie de rendu particulière et peut être utilisé avec des technologies Win32, Windows Forms, WPF ou encore HTML. Son indépendance vis-à-vis des technologies de rendu la positionne comme une technologie pérenne pour la mise en place de tests d’IHM automatisés et son architecture le rend par nature évolutif et ouvert à l’intégration d’autres technologies de rendu.
L’architecture
Microsoft UI Automation se compose de deux parties : la partie cliente, celle qui permet d’obtenir des informations sur les éléments visuels de l’interface, et la partie fournisseur, celle qui permet de fournir des informations aux applications clientes. Ainsi, pour reprendre l’exemple du test, l’application utilisant la partie cliente est l’application de test de l’interface, et l’application testée est celle qui utilise la partie fournisseur d’informations.
Le schéma ci-dessous présente l’architecture du Microsoft UI Automation.
.jpg)
Ce schéma d’architecture montre les deux parties communiquant des informations l’une à l’autre par l’intermédiaire du composant UIAutomationCore. Un des fondamentaux de cette architecture est qu’il n’existe pas de dépendances directes entre une application fournisseur et une application cliente. L’application cliente peut obtenir des informations sur l’application fournisseur sans avoir besoin de référencer l’un de ses composants ou d’avoir une dépendance quelconque. L’application cliente n’interagit avec l’application fournisseur que par l’intermédiaire d’UIAutomationCore et les éléments visuels de l’interface.
Les composants
Comme nous l’avons expliqué précédemment, UIAF peut s’utiliser de deux manières différentes :
- Consommer de l’information sur les éléments de l’interface (partie cliente),
- Ou fournir de l’information supplémentaire sur des éléments visuels (partie fournisseur).
Dans le premier cas, le développeur utilisera la « Client API » pour implémenter des tests ou consommer des informations. Dans le second cas, le développeur soucieux de rendre son application plus accessible utilisera la « Provider API ».
- Provider API : fournit un ensemble d’interfaces permettant d’émettre des informations sur les éléments d’IHM. Ce module se compose de 2 assemblies : UIAutomationProvider.dll et UIAutomationTypes.dll.
- Client API : Ce sont des classes .NET permettant d’obtenir/consommer des informations des éléments de l’IHM. Ce module se compose de 2 assemblies : UIAutomationClient.dll et UIAutomationTypes.dll.
- Une assembly « UIAutomationCore.dll » : c’est le code sous-jacent qui permet aux clients de l’API de consommer de l’information mise à disposition par les fournisseurs (« providers »).
- Une assembly « UIAutomationClientsideProviders.dll » : Un ensemble de fournisseurs d’automation UI pour le support des contrôles standards.
L’automation model
Dans cette partie, nous détaillons les éléments principaux de l’API cliente et du composant UIAutomationCore. Les éléments de l’automation model que nous allons voir vont nous permettre d’implémenter des tests d’IHM très facilement quelque soit la technologie de rendu. Pour faire bref et simple, le modèle peut se résumer de la manière suivante :
- L’automation tree : c’est l’arbre dans lequel une application cliente peut naviguer pour obtenir des informations ou interagir avec des éléments de l’interface. Le nœud racine de l’automation tree est le Bureau Windows (Desktop) et est accessible par l’objet AutomationElement.RootElement.
- Les automation elements : ce sont les éléments de l’interface, sous-entendu appartenant à l’automation tree. N’importe quel élément de l’interface peut-être obtenu via ses coordonnées X/Y, ou par le fait qu’il possède le focus, ou depuis un handle Windows (HWND) ou encore en naviguant au travers de l’automation tree.
- Les modèles de contrôles (Control Patterns) : un modèle de contrôle décrit les caractéristiques et fonctions d’un contrôle. C’est une interface avec des propriétés et méthodes. Par exemple, le modèle « TogglePattern » indique que le contrôle supporte la capacité à être coché ou décoché : cela peut-être une case à cocher (checkbox) ou un élément de menu sélectionnable par côche.
- Les types de contrôles (Control Types) : comme indiqué, cela représente le type d’un contrôle quelque soit sa technologie de rendu. Ainsi, un bouton Win32, Windows Forms ou WPF aura la propriété ControlType égale à « Button ».
- Les propriétés (AutomationProperty) : Ils existent deux catégories de propriétés : les propriétés natives, communes à tous les contrôles (exemple : Name, Enabled…), et les propriétés spécifiques aux modèles de contrôles.
- Les événements : La notification d’événement est un élément fondamental dans l’architecture du Microsoft UI Automation ; Ils permettent à une application cliente d’être notifiée dès que quelque chose se produit dans l’interface.
UI Spy
UI Spy est un utilitaire livré avec le Windows SDK Update pour Windows Vista. Il permet aux développeurs et testeurs de vérifier le niveau d’accessibilité d’une application. UI Spy donne des informations sur les propriétés et les modèles de contrôle supportés par un élément de l’interface, les événements générés sur l’interface ou une sous-partie de celle-ci, etc.
.jpg)
Illustration d’UI Spy avec l’application Calculator de Windows. L’automation tree est affiché dans la partie gauche de UI Spy et les propriétés de l’élément sélectionné dans la partie droite. La partie basse permet d’obtenir des informations de sortie notamment les événements générés.
Développer ses tests d’IHM
Pour illustrer le développement de tests d’IHM, nous utiliserons une application Windows simple : la calculatrice. Nous allons simuler un utilisateur qui souhaite calculer le produit de 5 et 3. Cet exemple simple nous permet de nous familiariser avec le Microsoft UI Automation indépendamment de la technologie de rendu de l’application testée (en l’occurrence, vous pouvez appliquer ces techniques sur vos propres applications).
L’application de test
Pour créer une application de test, exécutez votre IDE favori et créez un projet .NET framework 3.0. Une application Console peut suffire. Ajouter ensuite les références aux assemblies UIAutomationClient.dll et UIAutomationTypes.dll et déclarez le namespace « System.Windows.Automation ».
.jpg)
Récupération d’un élément de l’arbre
Les techniques de base consistent à utiliser différentes méthodes pour récupérer un élément de l’arbre visuel. Il est possible d’utiliser l’objet TreeWalker pour naviguer parmi les éléments avec des méthodes telles que « FindAll » pour récupérer tous les éléments de l’arbre qui satisfont une condition. Attention toutefois aux ressources consommées par les techniques de navigation car effectuer des recherches sur tout l’arbre des contrôles peut être très lent. La plupart du temps, nous utiliserons la fenêtre principale de notre application comme élément racine à notre navigation/nos recherches.
Le code ci-dessous montre la récupération de l’AutomationElement racine de la fenêtre de la calculatrice :
using System.Windows.Automation;
namespace SimpleTestCalc
{
class Program
{
static void Main(string[] args)
{
Process calculator = Process.Start("calc.exe");
// Attendre 5 secondes pour le démarrage de la calculatrice.
Thread.Sleep(5000);
// Récupération de l'AutomationElement racine de la calculatrice.
AutomationElement calcDialog = AutomationElement.FromHandle(calculator.MainWindowHandle);
Console.WriteLine("Titre de la fenêtre: {0}", calcDialog.Current.Name);
Console.WriteLine("[ENTREE] pour sortir.");
Console.ReadLine();
}
}
}Interagir avec l’IHM pour automatiser les tests
Pour implémenter maintenant notre scenario de test, nous devons simuler successivement l’appui sur les boutons « 3 », « * », « 5 » et enfin « = » pour obtenir le résultat et vérifier que cela fait bien « 15 ». Pour cela, il est nécessaire de récupérer une référence sur chacun des éléments visuels puis d’appliquer les modèles de contrôles (patterns) supportés : InvokePattern pour les boutons et TextPattern pour le champ de saisie de la calculatrice afin de récupérer le résultat. Le code est le suivant :
Condition name3Condition = new PropertyCondition(AutomationElement.NameProperty, "3");
AutomationElement button3 = calcDialog.FindFirst(TreeScope.Children, name3Condition);
Condition nameMulCondition = new PropertyCondition(AutomationElement.NameProperty, "*");
AutomationElement buttonMul = calcDialog.FindFirst(TreeScope.Children, nameMulCondition);
Condition name5Condition = new PropertyCondition(AutomationElement.NameProperty, "5");
AutomationElement button5 = calcDialog.FindFirst(TreeScope.Children, name5Condition);
Condition nameEqCondition = new PropertyCondition(AutomationElement.NameProperty, "=");
AutomationElement buttonEq = calcDialog.FindFirst(TreeScope.Children, nameEqCondition);
Condition typeEditCondition = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit);
AutomationElement resultEdit = calcDialog.FindFirst(TreeScope.Children, typeEditCondition);
InvokePattern clickButton = button3.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
clickButton.Invoke();
clickButton = buttonMul.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
clickButton.Invoke();
clickButton = button5.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
clickButton.Invoke();
clickButton = buttonEq.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
clickButton.Invoke();
TextPattern resultPattern = resultEdit.GetCurrentPattern(TextPattern.Pattern) as TextPattern;
int result = int.Parse(resultPattern.DocumentRange.GetText(2));
Debug.Assert(result == 15, "Erreur, le résultat n'est pas égal à 15");Les exemples de code livrés avec le Microsoft Automation Framework
Microsoft fournit quelques exemples d’implémentation avec UIAF pour montrer les différentes techniques d’interaction avec l’IHM. Un des exemples est un moteur d’enregistrement des actions de l’utilisateur sur une interface en WPF. A noter que WPF supporte nativement UIAF et permet de positionner des valeurs sur certaines propriétés d’UIAF directement dans le XAML (notamment l’AutomationId).
Concernant le moteur de génération des tests, la solution de cet exemple contient 3 projets :
- ExecuteScript : Projet d’exécution du script enregistré pendant la phase de tests.
- ScriptGeneratorClient : Projet de démarrage qui permet d’exécuter le lanceur d’applications chargé d’intercepter les événements de l’IHM.
- ScriptGeneratorTarget : Application exemple sur laquelle sera effectué l’enregistrement des actions.
Lancez le moteur en démarrant le projet ScriptGeneratorClient. Dans l’interface du générateur de script, cliquez sur « Start Target » et attendez que l’application exemple (ScriptGeneratorTarget) apparaisse. Ensuite cliquer sur « Start UI Automation » pour démarrer l’enregistrement, puis utilisez l’interface de l’application ScriptGeneratorTarget pour modifier ou sélectionner les valeurs affichées dans les contrôles WPF.
Lorsque vous avez fini vos tests, cliquez « Stop UI Automation » dans l’application ScriptGeneratorClient et cliquez sur « Generate Script » pour obtenir le code C# correspondant aux tests que vous avez effectués. Cliquez sur « Copy to Clipboard », fermez les deux applications et retournez dans Visual Studio. Ouvrez le fichier « Script.cs » dans le projet « ExecuteScript ». Supprimez le contenu du fichier puis collez le script enregistré.
Enregistrez les modifications faites dans le fichier « Script.cs » puis exécutez le projet « ExecuteScript ». Cliquez sur le bouton « Start Target » et attendez que l’application cible apparaisse. Cliquez ensuite sur le bouton « Execute Script », vous verrez l’ensemble des actions précédemment enregistrées se rejouer automatiquement.
Trois autres exemples sont fournis :
- FetchTimer : présente une utilisation du cache d’UIAF pour l’amélioration des performances.
- Highlighter : Exemple de modification de l’apparence du focus sur une interface.
- TrackFocus : Exemple de suivi du changement de Focus depuis le bureau Windows.
Conclusion
Dans cet article, nous avons introduit le Microsoft UI Automation Framework et les éléments principaux qui permettent aux développeurs d’accéder et d’interagir avec les éléments visuels d’une interface par programmation. Nous avons rapidement montré comment implémenter un test d’IHM en .NET pour une application WIN32 (la calculatrice de Windows). Cet exemple est généralisable à tous types d’applications (Windows Forms, WPF, etc.) et peut-être enrichit avec les nombreuses possibilités d’UIAF. A noter que des solutions de tests d’IHM apparaissent sur le marché et notamment le projet UIA Verify sur CodePlex ou encore l’outil de tests de la société Mpoware. Enfin, la future version de TFS (Rosario) devrait proposer une solution de test d’IHM.
Références