Xamarin.UITest

Important

Visual Studio App Center doit être mis hors service le 31 mars 2025. Bien que vous puissiez continuer à utiliser Visual Studio App Center jusqu’à ce qu’il soit entièrement mis hors service, il existe plusieurs alternatives recommandées vers lesquelles vous pouvez envisager de migrer.

En savoir plus sur les chronologies et les alternatives de support.

Xamarin.UITest est une infrastructure de test C# qui utilise NUnit pour les tests d’acceptation de l’interface utilisateur sur les applications iOS et Android. Il s’intègre étroitement aux projets Xamarin.iOS et Xamarin.Android, mais il peut également être utilisé avec des projets iOS et Android natifs. Xamarin.UITest est la bibliothèque Automation qui permet aux tests NUnit de s’exécuter sur des appareils Android et iOS. Les tests interagissent avec l’interface utilisateur comme le ferait un utilisateur : entrée de texte, appui sur des boutons et mouvements, tels que des balayages.

En règle générale, chaque Xamarin.UITest est écrit en tant que méthode appelée [Test]. La classe qui contient le test est appelée [TestFixture]. La fixation de test contient un seul test ou un groupe de tests. Le montage est également responsable de l’installation pour effectuer l’exécution de test et le nettoyage qui doit être effectué à la fin du test. Chaque test doit suivre le modèle Arrange-Act-Assert :

  1. Organiser : le test va configurer les conditions et initialiser les éléments afin que le test puisse être actionné.
  2. Agir : le test interagit avec l’application, entre du texte, appuie sur des boutons, etc.
  3. Assert : le test examine les résultats des actions exécutées à l’étape Act pour déterminer l’exactitude. Par exemple, l’application peut vérifier qu’un message d’erreur particulier est affiché.

Le meilleur moment pour commencer à utiliser Xamarin.UITest est pendant le développement d’une application mobile. Les tests automatisés sont écrits au fur et à mesure qu’une fonctionnalité est en cours de développement conformément aux étapes décrites dans la liste suivante :

  1. Développez la fonctionnalité dans l’application Android ou iOS.
  2. Écrivez les tests et exécutez-les localement pour vérifier leur fonctionnalité.
  3. Créez une nouvelle série de tests dans App Center Test ou utilisez une série de tests existante.
  4. Compilez l’IPA ou l’APK, puis chargez-le avec les tests dans App Center Test.
  5. Corrigez les problèmes ou bogues exposés par le test App Center.
  6. Répétez le processus en passant à la fonctionnalité suivante pour l’application.

Pour les applications existantes qui ne sont plus en cours de développement actif, il peut ne pas être rentable d’ajouter rétroactivement des tests automatisés. Au lieu de cela, une meilleure approche consiste à utiliser Xamarin.UITest pour corriger les bogues. Par exemple, considérez une application qui n’a aucun test automatisé et un utilisateur signale un bogue. Un développeur affecté à la correction de ce bogue peut effectuer une partie (ou la totalité) des actions suivantes :

  • Vérifiez manuellement le bogue ou la régression.
  • Écrivez un test à l’aide de Xamarin.UITest qui illustre le bogue.
  • Envoyez le test au test App Center pour obtenir des informations sur l’étendue et l’impact du bogue sur les appareils appropriés.
  • Corriger le bogue.
  • Prouvez que le bogue a été résolu avec un Xamarin.UITest passant.
  • Soumettez les correctifs et testez à App Center Test pour vérifier que le bogue a été résolu sur les appareils appropriés.
  • Vérifiez la réussite des tests dans le contrôle de version.

Les tests automatisés de l’interface utilisateur reposent fortement sur la localisation et l’interaction avec les vues à l’écran. Xamarin.UITest répond à cette exigence avec deux ensembles importants d’API qui fonctionnent les unes avec les autres :

  1. Actions qui peuvent être effectuées sur les vues : Xamarin.UITest fournit des API qui permettent à un test de simuler des actions utilisateur courantes telles que le fait d’appuyer sur l’affichage, d’entrer du texte ou de balayer sur l’affichage.
  2. Requêtes pour localiser les affichages sur l’écran - Une partie de l’infrastructure Xamarin.UITest sont des API qui localiseront les vues sur un écran. Les requêtes localisent les vues au moment de l’exécution en inspectant les attributs de la vue et en retournant un objet sur lequel les actions peuvent fonctionner. Interroger de cette manière est une technique puissante qui permet d’écrire des tests pour les interfaces utilisateur quelle que soit la taille, l’orientation ou la disposition de l’écran

Pour faciliter l’écriture de tests, Xamarin.UITest fournit une boucle en lecture-eval-print-loop (REPL). RepL permet aux développeurs et aux testeurs d’interagir avec un écran pendant l’exécution de l’application et simplifie la création des requêtes.

Présentation de l’API Xamarin.UITest

Toutes les interactions de test avec l’application mobile se produisent via un instance de Xamarin.UITest.IApp. Cette interface définit les méthodes qui sont essentielles pour que le test collabore avec l’application et interagit avec l’interface utilisateur. Il existe deux implémentations concrètes de cette interface :

  • Xamarin.UITest.iOS.iOSApp Cette classe automatisera les tests sur iOS.
  • Xamarin.UITest.Android.AndroidApp Cette classe permet d’automatiser les tests sur Android.

iOSApp et AndroidApp les objets ne sont pas instanciés directement. Au lieu de cela, ils sont créés à l’aide de la classe d’assistance ConfigureApp . Cette classe est un générateur qui garantit que ou iOSAppAndroidApp est correctement instancié.

Nous vous recommandons d’utiliser une nouvelle IApp instance pour chaque test. Une nouvelle instance empêche l’état d’un test de basculer dans un autre. Il existe deux endroits où un test NUnit peut initialiser un instance de IApp:

  • Dans la SetUp méthode Généralement, une fixation de test est un regroupement logique de tests associés, chacun d’eux s’exécutant indépendamment de l’autre. Dans ce scénario, le IApp doit être initialisé dans la SetUp méthode, en veillant à ce qu’un nouveau IApp soit disponible pour chaque test.
  • Dans la TestFixtureSetup méthode Dans certaines situations, un seul test peut nécessiter sa propre fixation de test. Dans ce cas, il peut être plus judicieux d’initialiser l’objet IApp une fois dans la TestFixtureSetup méthode.

Une fois IApp configuré, un test peut commencer à interagir avec l’application en cours de test. Pour ce faire, il est nécessaire d’obtenir des références aux vues visibles à l’écran. De nombreuses méthodes dans Xamarin.UITest prennent un Func<AppQuery, AppQuery> paramètre pour localiser les vues. Par exemple, l’extrait de code suivant montre comment appuyer sur un bouton :

app.Tap(c=>c.Button("ValidateButton"));

Il existe deux implémentations de l’interface dans l’infrastructure IApp Xamarin.UITest, une pour iOS et une pour Android.

Initialiser IApp pour les applications iOS

Lorsque Xamarin.UITest exécute un test sur iOS, il démarre une instance du simulateur iOS, déploie l’application, la lance et commence à exécuter les tests. L’application iOS doit déjà être générée. Xamarin.UITest ne compile pas l’application et ne crée pas l’ensemble d’applications pour vous.

La AppBundle méthode peut être utilisée pour spécifier où se trouve le bundle d’application sur le système de fichiers. Il existe deux façons de procéder, avec un chemin absolu ou un chemin relatif. Cet extrait de code montre l’utilisation d’un chemin d’accès absolu à l’offre groupée d’applications :

IApp app = ConfigureApp
    .iOS
    .AppBundle("/path/to/iosapp.app")
    .StartApp();

Les chemins d’accès partiels doivent être relatifs à l’assembly Xamarin.UITest. Cet extrait de code est un exemple :

IApp app = ConfigureApp
    .iOS
    .AppBundle("../../../iOSAppProject/bin/iPhoneSimulator/Debug/iosapp.app")
    .StartApp();

L’exemple de chemin relatif indique AppBundle de monter trois répertoires à partir de l’assembly Xamarin.UITest, puis de naviguer dans l’arborescence du projet du projet d’application iOS pour rechercher l’offre groupée d’applications.

ConfigureApp dispose d’autres méthodes pour vous aider à configurer IApp. Pour plus d’informations, consultez la classe iOSAppConfigurator . Certaines des méthodes les plus intéressantes sont décrites dans le tableau suivant :

Méthode Description
AppBundle Cette méthode spécifie le chemin d’accès au bundle d’applications à utiliser lors du test.
Debug Cette méthode permet de déboguer les messages de journalisation dans l’exécuteur de test. Cette méthode est utile pour résoudre les problèmes liés à l’exécution de l’application sur le simulateur.
DeviceIdentifier Configure l’appareil à utiliser avec l’identificateur de l’appareil. Cette méthode sera décrite plus en détail ci-dessous.
EnableLocalScreenshots Activer les captures d’écran lors de l’exécution de tests localement. Les captures d’écran sont toujours activées lorsque des tests s’exécutent dans le cloud.

Pour plus d’informations sur l’exécution de tests iOS sur un simulateur iOS spécifique, consultez Déterminer l’ID d’appareil pour un simulateur iOS.

Initialiser IApp pour les applications Android

Xamarin.UITest déploie un FICHIER APK existant sur un appareil attaché ou un instance de l’émulateur Android déjà en cours d’exécution. L’application est démarrée, puis le test est exécuté. Xamarin.UITest ne peut pas générer l’APK et ne peut pas démarrer une instance de l’émulateur Android.

La ApkFile méthode de IApp est utilisée pour spécifier où se trouve l’APK sur le système de fichiers. Il existe deux façons de procéder, avec un chemin absolu ou un chemin relatif. Cet extrait de code montre l’utilisation d’un chemin d’accès absolu à l’APK :

IApp app = ConfigureApp
    .Android
    .ApkFile("/path/to/android.apk")
    .StartApp();

Les chemins d’accès partiels doivent être relatifs à l’assembly Xamarin.UITest. Cet extrait de code est un exemple :

IApp app = ConfigureApp
    .Android
    .ApkFile("../../../AndroidProject/bin/Debug/android.apk")
    .StartApp();

L’exemple de chemin relatif indique ApkFile de monter trois répertoires à partir de l’assembly Xamarin.UITest, puis de naviguer dans l’arborescence du projet de l’application Android pour trouver le fichier apk.

Si plusieurs appareils ou émulateurs sont connectés, Xamarin.UITest arrête l’exécution des tests et affiche un message d’erreur, car il ne peut pas résoudre la cible prévue pour le test. Dans ce cas, il est nécessaire de fournir l’ID série de l’appareil ou de l’émulateur pour exécuter le test. Par exemple, considérez la sortie suivante de la adb devices commande qui répertorie tous les appareils (ou émulateurs) attachés à l’ordinateur (avec leur ID série) :

$ adb devices
List of devices attached
192.168.56.101:5555 device
03f80ddae07844d3    device

L’appareil peut être spécifié à l’aide de la DeviceSerial méthode :

IApp app = ConfigureApp.Android.ApkFile("/path/to/android.apk")
                               .DeviceSerial("03f80ddae07844d3")
                               .StartApp();

Interaction avec l’interface utilisateur

Pour interagir avec les vues, de nombreuses IApp méthodes prennent un Func<AppQuery, AppQuery> délégué pour localiser la vue. Ce délégué utilise AppQuery cela au cœur de la façon dont Xamarin.UITest localise les vues.

AppQuery est une interface Fluent permettant de générer les requêtes afin de localiser des vues. Parmi les méthodes fournies AppQuery , la Marked méthode est l’une des plus simples et des plus flexibles. Cette méthode utilise une heuristique pour tenter de localiser les vues et sera traitée plus en détail dans la section suivante. Pour l’instant, il est important de comprendre qu’il IApp existe de nombreuses méthodes pour interagir avec une application. Ces méthodes utilisent un Func<AppQuery, AppQuery> pour obtenir une référence à la vue avec laquelle interagir. Voici quelques-unes des méthodes les plus intéressantes fournies par AppQuery :

Méthode Description
Button Recherche un ou plusieurs boutons à l’écran.
Class Tente de localiser les vues qui sont d’une classe spécifiée.
Id Tente de localiser une vue avec l’ID spécifié.
Index . Retourne une vue à partir d’une collection d’affichages correspondants. Généralement utilisé conjointement avec d’autres méthodes. Prend un index de base zéro.
Marked Retourne une vue en fonction de l’heuristique décrite ci-dessous.
Text Correspond aux vues qui contiennent le texte fourni.
TextField Correspond à un Android EditText ou iOS UITextField.

Par exemple, la méthode suivante montre comment simuler un appui sur un bouton appelé « SaveUserdataButton » :

app.Tap(c=>c.Marked("SaveUserDataButton"));

Étant donné que AppQuery est une interface Fluent, il est possible de chaîner plusieurs appels de méthode ensemble. Considérez cet exemple plus complexe d’appui sur une vue :

app.Tap(c=>c.Marked("Pending")
            .Parent()
            .Class("AppointmentListCell").Index(0));

Ici, le AppQuery trouvera d’abord une vue marquée Pending, puis sélectionnez le premier parent de cette vue qui est un AppointmentListCell type.

Il peut être difficile d’essayer de créer ces requêtes en examinant une application mobile. Xamarin.UITest fournit un REPL qui peut être utilisé pour explorer la hiérarchie d’affichage d’un écran, expérimenter la création de requêtes et les utiliser pour interagir avec une application.

Utilisation de REPL

La seule façon de démarrer le REPL consiste à appeler la IApp.Repl méthode dans un test existant. Cela nécessite la création d’un NUnit TestFixture, la configuration d’un instance de IApp qui peut être utilisé dans une Test méthode. L’extrait de code suivant montre un exemple de procédure à suivre :

[TestFixture]
public class ValidateCreditCard
{
    IApp app;

    [SetUp]
    public void Setup()
    {
        app = ConfigureApp.Android.ApkFile("/path/to/application.apk").StartApp();
    }
    [Test]
    public void CreditCardNumber_TooLong_DisplayErrorMessage()
    {
        app.Repl();
    }
}

Pour exécuter le test en cliquant avec le bouton droit dans la gouttière de Visual Studio et en sélectionnant Exécuter :

Capture d’écran du menu contextuel avec les options d’exécution d’un test

Le test s’exécute et, lorsque la Repl méthode est appelée, Xamarin.UITest démarre le REPL dans une session de terminal, comme illustré dans la capture d’écran suivante :

Capture d’écran du terminal macOS exécutant Xamarin.UITest REPL

Le REPL a initialisé une instance de IApp qui s’appelle app, qui interagit avec l’application. L’une des premières choses à faire est d’explorer l’interface utilisateur. RepL dispose d’une tree commande pour ce faire. Il imprime la hiérarchie des vues dans l’écran affiché. Prenons l’exemple de la capture d’écran suivante d’une application :

Capture d’écran d’un exemple d’application s’exécutant sur un iPhone

Nous pouvons utiliser la tree commande pour afficher la hiérarchie suivante de cet écran :

App has been initialized to the 'app' variable.
Exit REPL with ctrl-c or see help for more commands.

>>> tree
[UIWindow > UILayoutContainerView]
  [UINavigationTransitionView > ... > UIView]
    [UITextView] id: "CreditCardTextField"
      [_UITextContainerView]
    [UIButton] id: "ValidateButton"
      [UIButtonLabel] text: "Validate Credit Card"
    [UILabel] id: "ErrorrMessagesTestField"
  [UINavigationBar] id: "Credit Card Validation"
    [_UINavigationBarBackground]
      [_UIBackdropView > _UIBackdropEffectView]
      [UIImageView]
    [UINavigationItemView]
      [UILabel] text: "Credit Card Validation"
>>>

Nous pouvons voir qu’il y a un UIButton dans cette vue avec le id de ValidateButton. Nous pouvons utiliser les informations affichées par la tree commande pour créer les requêtes nécessaires à la localisation et à l’interaction avec les vues. Par exemple, le code suivant simule un appui sur le bouton :

app.Tap(c=>c.Marked("ValidateButton"))

À mesure que les commandes sont entrées, elles sont mémorisées par le REPL dans une mémoire tampon. Repl fournit une copy commande qui copie le contenu de cette mémoire tampon dans le Presse-papiers. Cela nous permet de prototyper un test. Nous pouvons copier le travail effectué dans le REPL dans le Presse-papiers avec copy, puis coller ces commandes dans un [Test].

Utilisation de Marqué pour localiser les affichages

La méthode AppQuery.Marked est un moyen pratique et puissant d’interroger les vues à l’écran. Il fonctionne en inspectant la hiérarchie d’affichage pour une vue à l’écran, en essayant de faire correspondre les propriétés de l’affichage avec à la chaîne fournie. Marked fonctionne différemment selon le système d’exploitation.

Recherche d’affichages iOS avec marqué

Les vues iOS sont situées à l’aide de l’un des attributs suivants :

  • de AccessibilityIdentifier la vue
  • de AccessibilityLabel la vue

Prenons l’exemple de l’extrait de code C# suivant qui crée un UILabel et définit :AccessibilityLabel

UILabel errorMessagesTextField = new UILabel(new RectangleF(10, 210, 300, 40));
errorMessagesTextField.AccessibilityLabel = "ErrorMessagesTextField";
errorMessagesTextField.Text = String.Empty;

Cette vue peut être localisée par la requête suivante :

AppResult[] results = app.Marked("ErrorMessagesTextField");

Recherche d’affichages Android avec marqué

Les vues Android sont basées sur l’une des propriétés suivantes :

  • de Id la vue
  • de ContentDescription la vue
  • d’une Text vue

Prenons l’exemple d’une disposition Android pour laquelle le bouton suivant est défini :

<Button
    android:text="Action 1"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:id="@+id/action1_button"
    android:layout_weight="1"
    android:layout_marginLeft="5dp" />

Nous pouvons voir que le android:id de ce bouton est action1_button et que est Action android:text1. L’une des deux requêtes suivantes recherche le bouton à l’écran :

  • app.Query(c=>c.Marked("action1_button"));
  • app.Query(c=>c.Marked("Action 1"));

Contrôle de l’application avec Xamarin.UITest.IApp

Une fois IApp configuré et initialisé, le test peut commencer à interagir avec l’application. La méthode est IApp.Query() un exemple de méthode utilisant Func<AppQuery, AppQuery> . Cette méthode exécute la requête et retourne les résultats. L’exemple le plus simple est illustré dans l’extrait de code suivant, qui retourne une liste de toutes les vues visibles à l’écran :

AppResult[] results = app.Query(c=>c.All())

Le tableau suivant illustre d’autres exemples d’utilisation AppQuery de pour localiser des affichages à l’écran :

Syntaxe Résultats
app.Query(c=>c.Class("UILabel")) La .Class() méthode interroge les vues qui sont une sous-classe d’un iOS UILabel.
app.Query(c=>c.Id("txtUserName")) La .Id() méthode interroge les vues avec un IdtxtUserName.
app.Query(c=>c.Class("UILabel").Text("Hello, World")) Recherche toutes les UILabel classes dont le texte est « Hello, World ».
results = app.Query(c=>c.Marked("ValidateButton")) Retourne toutes les vues marquées avec le texte spécifié. La Marked méthode est une méthode utile qui peut simplifier les requêtes. Elle sera traitée dans la section suivante.

Le tableau suivant répertorie certaines (mais pas toutes) des méthodes fournies par IApp qui peuvent être utilisées pour interagir avec ou manipuler des vues à l’écran :

Exemple Description
PressEnter Appuyez sur la touche Entrée dans l’application.
Tap Simule un mouvement d’appui/tactile sur l’élément correspondant.
EnterText Entre du texte dans la vue. Dans une application iOS, Xamarin.UITest entre le texte à l’aide du clavier logiciel. En revanche, Xamarin.UITest n’utilise pas le clavier Android, il entre directement le texte dans l’affichage.
WaitForElement Interrompt l’exécution du test jusqu’à ce que les affichages s’affichent à l’écran.
Screenshot(String) Prend une capture d’écran de l’application dans son état actuel et l’enregistre sur le disque. Elle retourne un FileInfo objet avec des informations sur la capture d’écran effectuée.
Flash Cette méthode entraîne le « flash » ou le « scintillement » de l’affichage sélectionné à l’écran.

Pour plus d’informations sur l’interface IApp , consultez la documentation de l’API pour IApp, AndroidAppet iOSApp.

À titre d’exemple d’utilisation de ces méthodes, envisagez le test suivant pour la capture d’écran affichée ci-dessus. Ce test entre un nombre à 17 chiffres pour un crédit carte dans un champ de texte, puis appuie sur un bouton à l’écran. Il inspecte ensuite l’écran à la recherche d’un message d’erreur informant l’utilisateur que le numéro est trop long pour être un crédit carte numéro valide :

[Test]
public void CreditCardNumber_TooLong_DisplayErrorMessage()
{
    /* Arrange - set up our queries for the views */
    // Nothing to do here, app has been instantiated in the [SetUp] method.

    /* Act */
    app.EnterText(c => c.Marked("CreditCardTextField"), new string('9', 17));
    // Screenshot can be used to break this test up into "steps".
    // The screenshot can be inspected after the test run to verify
    // the visual correctness of the screen.
    app.Screenshot("Entering a 17 digit credit card number.");

    app.Tap(c => c.Marked("ValidateButton"));
    app.Screenshot("The validation results.");

    /* Assert */
    AppResult[] result = app.Query(c => c.Class("UILabel").Text("Credit card number is too long."));
    Assert.IsTrue(result.Any(), "The error message isn't being displayed.");
}

Ce test utilise également la Screenshot méthode pour prendre des photos à des points clés pendant l’exécution du test. Lorsque ce test est exécuté, App Center prend les captures d’écran et les affiche dans les résultats du test. La méthode permet de diviser un test en étapes et de fournir des descriptions pour les captures d’écran.