Moniteur en mode utilisateur
Le moniteur du mode utilisateur permet aux tests d’obtenir plus de contexte sur l’exécution du « processus testé » afin d’obtenir davantage de contexte pour examiner les échecs de test ou pour permettre une meilleure vérification à partir des tests existants. L’implémentation actuelle du moniteur en mode utilisateur fournit une implémentation de base, avec davantage de personnalisation et de configuration dans les versions suivantes.
Introduction
Le moniteur de mode utilisateur (UMM) utilise des API Windows de bas niveau pour être averti de tous les événements de « débogueur » qui proviennent d’un processus donné : démarrage et arrêt du thread, chargement du module, incidents et exceptions gérées, pour n’en citer que quelques-uns. Lors de la réception d’un événement de débogueur, le code UMM peut effectuer l’une des différentes actions, notamment la journalisation des commentaires, la journalisation des erreurs (afin d’échouer à un test) ou même l’exécution d’un minidump du processus en cours de test.
Activation du moniteur en mode utilisateur
Pour activer l’UMM pour un cas de test donné, vous devez fournir deux éléments de configuration :
- Le test doit être marqué avec la valeur de métadonnées « ProcessUnderTest ». Cela permet à l’UMM d’identifier le processus testé.
- La ligne de commande Te.exe doit inclure « /userModeMonitor » pour activer la fonctionnalité UMM.
Les points suivants doivent être pris en compte lors de l’utilisation du code UMM :
- Si plusieurs instances du processus nommé sous test sont en cours d’exécution, le instance qui est découvert en premier est utilisé.
- L’utilisateur qui exécute l’automatisation du test doit disposer des autorisations suffisantes pour recevoir des événements de débogueur à partir du processus en cours de test.
- Le code UMM « s’attache » au processus en cours de test une fois que tous les montages d’installation ont été exécutés, et « détache » avant l’exécution des montages de nettoyage. Cela permet aux montages d’installation d’un test de démarrer le processus en cours de test et d’effectuer toute initialisation nécessaire pour se préparer au test.
Actions prises en charge du moniteur en mode utilisateur
Le moniteur de mode utilisateur a un ensemble d’actions qu’il peut effectuer lorsqu’un événement de débogueur donné se produit dans le processus surveillé. Dans l’implémentation actuelle, un événement donné appelle uniquement son action par défaut ; il n’existe actuellement aucune prise en charge de la configuration.
Action | Description |
---|---|
LogComment | Ajoute un commentaire au journal, avec des informations contextuelles de l’événement. |
LogError | Enregistre une erreur dans le journal, ce qui échoue au test actuel. |
Minidump | Écrit un minidump et l’enregistre dans le journal. |
Ignorer | Ne fait rien. |
« Événements » du moniteur du mode utilisateur pris en charge
Le moniteur du mode utilisateur affiche des « événements » qui peuvent appliquer l’une des « actions » répertoriées ci-dessus. Le tableau suivant présente la liste actuelle des événements signalés, ainsi que l’action par défaut qui sera effectuée lors de la réception de l’événement.
événement | Action par défaut (action par défaut de la deuxième chance) |
---|---|
Créer un thread | Ignorer |
Thread de sortie | Ignorer |
Créer un processus | Ignorer |
Processus de sortie | LogError |
Module de chargement | LogComment |
Décharger le module | Ignorer |
Erreur système | Ignorer |
Point d’arrêt initial | LogError |
Chargement initial du module | Ignorer |
Sortie de débogage | LogComment |
Violation d’accès | LogError (LogError) |
Échec d’assertion | LogError (LogError) |
Blocage de l’application | LogError (LogError) |
Exception d’instruction d’arrêt | LogError |
Arrêt de l’exception d’instruction continue | Ignorer |
Exception EH C++ | LogError (LogError) |
Exception CLR | LogError (LogError) |
Exception de notification CLR | LogError (Ignorer) |
Control-LogError exception | LogError |
Control-LogError exception continue | Ignorer |
Exception Control-C | LogError |
L’exception Control-C continue | Ignorer |
Données mal alignées | LogError (LogError) |
Exception de commande débogueur | Ignorer |
Violation de page de protection | LogError (LogError) |
Instruction non conforme | LogError (LogError) |
Erreur d’E/S dans la page | LogError (LogError) |
Entier divisé par zéro | LogError (LogError) |
Dépassement de capacité d’entier | LogError (LogError) |
Handle non valide | LogError |
Continue du handle non valide | LogError |
Séquence de verrous non valide | LogError (LogError) |
Appel système non valide | LogError (LogError) |
Port déconnecté | LogError (LogError) |
Blocage du service | LogError (LogError) |
Exception à étape unique | LogError |
L’exception à étape unique continue | Ignorer |
Dépassement de mémoire tampon au niveau de la pile | LogError (LogError) |
Dépassement de capacité de la pile | LogError (LogError) |
Arrêt du vérificateur | LogError (LogError) |
Exception Visual C++ | Ignorer (Ignorer) |
Débogueur de veille | LogError (LogError) |
Point d’arrêt WOW64 | LogError (Ignorer) |
Exception d’étape unique WOW64 | LogError (Ignorer) |
Autre exception | LogError (LogError) |
Exemple
Pour illustrer l’utilisation de la fonctionnalité UMM, examinons un exemple (légèrement artificiel) d’un test qui automatise « MSPaint » :
namespace UserModeMonitorExample
{
using System;
using System.Diagnostics;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WEX.Logging.Interop;
using WEX.TestExecution;
[TestClass]
public class BasicExample
{
[TestInitialize]
public void TestInitialize()
{
Process[] runningPaintInstances = Process.GetProcessesByName("mspaint.exe");
Verify.IsTrue(runningPaintInstances.Length == 0, "There are no running instances of mspaint.exe");
this.mspaintUnderTest = Process.Start("mspaint.exe");
}
[TestCleanup]
public void TestCleanup()
{
// Close the 'mspaint under test' - if it's already gone, this will throw, but that's no big deal.
this.mspaintUnderTest.CloseMainWindow();
}
[TestMethod]
[TestProperty("ProcessUnderTest", "mspaint.exe")]
[TestProperty("Description", "Shows how a test can be failed if the UI is closed from underneath the test.")]
public void SimpleInteraction()
{
Log.Comment("If the 'user mode monitor' is enabled and mspaint.exe is closed,");
Log.Comment("then this test will be failed.");
Log.Comment("Sleeping for 5 seconds");
Thread.Sleep(TimeSpan.FromSeconds(5));
}
private Process mspaintUnderTest;
}
}
Voici une rapide répartition de la structure du test :
- Le test « SimpleInteraction » représente un test qui interagit avec une application basée sur l’interface utilisateur. Dans ce cas, il s’agit de « MSPaint.exe ». Notez que les métadonnées « ProcessUnderTest » ont été appliquées pour signaler que ce test test teste le processus « mspaint.exe ».
- Le test a une fixation d’installation qui garantit qu’aucune instance préexistante n’est en cours d’exécution et lance une seule instance à tester.
- Le test a également un appareil de nettoyage qui ferme le instance qui a été lancé dans le montage d’installation.
Le « test » est très simple, examinons les résultats possibles :
- Le test s’exécute sans problème. C’est le meilleur résultat possible.
- Sans UMM activé, un utilisateur ferme le instance MSPaint pendant l’exécution. Dans ce cas, le test est réussi, mais le nettoyage échoue avec une « InvalidOperationException ».
- Avec UMM activé, un utilisateur ferme le instance MSPaint pendant l’exécution. Dans ce cas, le code UMM journalisera une erreur indiquant que le processus s’est fermé en échouant au test. Le nettoyage échoue comme dans le cas (2).
Avec UMM activé, le comportement errant est immédiatement signalé et affecte directement le résultat du test. Il s’agit d’un modèle de test bien meilleur, car les erreurs sont signalées le plus tôt possible et un contexte supplémentaire est fourni pour faciliter le débogage ou la compréhension des échecs de test.