Fermer

juin 1, 2021

Automatisez vos applications WPF avec Appium


L'automatisation des tests joue un rôle important dans le développement d'applications. Permettez-moi de partager une procédure pas à pas sur la façon dont vous pouvez automatiser votre application WPF à l'aide de Appium avec Pilote d'application Windows et UI Recorder outil.

Chaque automatisation de test a besoin un cadre sur lequel il peut s'appuyer. L'un de ces frameworks est Appiumutilisé pour les applications Web natives, hybrides et mobiles. Il couvre les plateformes iOS, Android et Windows. Aujourd'hui, je vais me concentrer sur la manière dont votre application WPF peut en bénéficier.

À quoi s'attendre dans cette histoire?

Je vais sauter la configuration de l'application WPF, car ce n'est pas notre objectif ici. Il s'agit d'une simple démo d'application de messagerie avec des fonctionnalités limitées aux fins de cet article. Ce que je vais faire, c'est vous guider tout au long du processus de création de votre projet de test, de sa configuration, puis de l'écriture de plusieurs scénarios de test. Une démo fonctionnelle complète est disponible dans le référentiel suivant : Get-your-WPF-apps-automated-with-Appium.

Demo mail app inbox

Prérequis

  1. Télécharger le Pilote d'application Windows . Il s'agit d'un service qui prend en charge le test des applications Universal Windows Platform (UWP), Windows Forms (WinForms), Windows Presentation Foundation (WPF) et Windows classique (Win32) sur Windows 10.
  2. Activer Mode développeur pour Windows en tapant « pour les développeurs» dans le menu Démarrer, puis activez la fonction.
  3. Installez le Windows Application Driver .
  4. Download ] le code source WinAppDriver pour que vous puissiez bénéficier de l'outil UI Recorder .

Configuration du projet de test

  1. Ouvrez votre Visual Studio et créez un nouveau projet de test unitaire (.NET Core) avec .NET 5.0 comme framework cible . Appelons-le MailApp.Tests.
  2. Cliquez avec le bouton droit sur le projet et sélectionnez "Gérer les packages NuGet". Vous pouvez également utiliser la séquence de clavier Alt T N N sans maintenir la touche Alt enfoncée.
  3. Sélectionnez nuget.org comme source du package et installez le Appium.WebDriver NuGet.

NuGet Pacakge Manager : MailApp.Tests définit la source du package comme nuget.org. Il y a un bouton de lecture à côté d'Appium.WebDriver, et une dernière version stable avec un bouton d'installation.

Base Class and Tests Session

  1. Créez une nouvelle classe appelée TestsBase où tous les paramètres Appium et le l'initialisation de la session sera décrite.
  2. Créez une méthode StartWinAppDriver() pour démarrer le service.

    private static void StartWinAppDriver()

    {

    ] ProcessStartInfo psi = nouveau ProcessStartInfo (WinAppDriverPath);

    psi.UseShellExecute = true ;

    psi.Verb = "runas" ; // exécuter en tant qu'administrateur

    winAppDriverProcess = Process.Start(psi);

    }

    Le paramètre WinAppDriverPath est le chemin d'accès au service.

  3. Au début de notre classe, nous définissons plusieurs constantes pour contenir des informations spécifiques utilisées pour configurer notre session.

    private const string ApplicationPath = @".. ......MailAppbinReleasenet5.0-windowsMailApp.exe";

    private const string DeviceName = " WindowsPC";

    private const int WaitForAppLaunch = 5;

    private const string WinAppDriverPath = @"C: Program Files (x86)Windows Application DriverWinAppDriver.exe";

    private static Process winAppDriverProcess;

    public WindowsDriver AppSession { get[19659032]; ensemble privé  ; }

    public WindowsDriver DesktopSession { get; ensemble privé ; }

    Le WindowsApplicationDriverUrl est l'URL du service WinAppDriver. Cela peut être vu dans l'outil de ligne de commande qui apparaît au démarrage du service. Nous avons d'autres constantes spécifiant d'autres chemins et paramètres que nous souhaitons transmettre.

  4. Créez une méthode Initialize qui utilise les constantes ci-dessus. La méthode sera appelée plus tard dans une classe de test contenant nos tests. Nous avons défini différentes options en utilisant la méthode AddAdditionalCapability d'AppiumOptions. La fonctionnalité « app » est obligatoire : elle contient l'identifiant de notre application de test.

    public void Initialize()

    {

    StartWinAppDriver();

    var appiumOptions = [19659028]new AppiumOptions();

    appiumOptions.AdditionalCapability("app"ApplicationPath);

    appiumOptions.AdditionalCapability("deviceName"DeviceName);[19659030]appiumOptions.AdditionalCapability("ms:waitForAppLaunch"WaitForAppLaunch);

    this.AppSession = new WindowsDriver(new new[Uri(WindowsApplicationDriverUrl)appiumOptions);

    Assert.IsNotNull(AppSession);

    Assert.IsNotNull(AppSession.SessionId);

    AppSession.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconSecon );

    AppiumOptions optionsDesktop = new AppiumOptions();

    optionsDesktop.AdditionalCapability([1 9659034]"app""Root");

    optionsDesktop.AdditionalCapability("deviceName"DeviceName);

    DesktopSession = new[19659025]WindowsDriver(new Uri(WindowsApplicationDriverUrl), optionsDesktop);

    CloseTrialDialog();

    }

    Vous avez probablement remarqué que nous avons deux sessions WindowsDriver—une appelée AppSession et l'autre appelée DesktopSession. AppSession contrôle l'application que nous testons tandis que DesktopSession contrôle les boîtes de dialogue supplémentaires qui peuvent apparaître. Ils ne font pas partie de la même arborescence visuelle, et Appium ne pourra pas trouver les éléments. Pour rechercher dans toutes les applications de bureau ouvertes, nous devons créer une autre DesktopSession avec l'identifiant racine pour la capacité « application ».

    Notre application de démonstration utilise l'interface utilisateur d'essai Telerik pour les binaires WPF et nous devons fermer la boîte de dialogue d'avertissement d'essai avant chaque test. Nous le faisons avec la méthode CloseTrialDialog().

    protected void CloseTrialDialog ()

    {

    this .GetElementByName ( "Telerik UI for WPF Trial" ). FindElementByName (). FindElementByName () ]"Cancel").Click();

    }

  5. Dans la classe TestsBase, nous créons deux autres méthodes :
    • CleanUp() – pour fermer l'application lorsque nous n'en avons plus besoin
    • StopWinAppDriver() – pour fermer le service WinAppDriver

    public void Cleanup ()

    {

    // Fermer la session

    if (AppSession! = null ) [19659030]{

    AppSession.Close();

    AppSession.Quit();

    }

    // Fermez la session desktop

    if (DesktopSession != null )

    {

    DesktopSession.Close();

    DesktopSession.Quit();

    }

    }

    public static void StopWinappDriver()[19659026]{

    // Arrêter le WinAppDriverProcess

    if (winAppDriverProcess != null)

    {

    foreach (var process in[19659025]Process.GetProcessesByName("WinAppDriver"))

    {

    process.Kill();

    }

    }

    }

  6. Créons méthodes utiles pour effectuer des opérations au clavier et sélectionner du texte. Nous les ajouterons à la classe TestBase .

    Appium a une solution pour de telles opérations— Actions . Nous créons une instance Actions en passant la session en tant que paramètre, dans notre cas, la AppSession. Ensuite, nous devons enregistrer les opérations de clavier que nous voulons et, à la fin, appeler Perform() pour exécuter la séquence d'actions.

    protected void SelectAllText ()

    {

    Actions action = new Actions(AppSession);

    action.KeyDown(Keys.Control).SendKeys("a");[19659030]action.KeyUp(Keys.Control);

    action.Perform();

    }

    protected void PerformDelete()

    {

    Actions action = [19659028]new Actions(AppSession);

    action.SendKeys(Keys.Delete);

    action.Perform();

    }

    protégé void[19659025]PerformEnter()

    {

    Actions action = new Actions(AppSession);

    action.SendKeys(Keys.Enter);

    action.Perform();[19659038]}

    protected void WriteText(string text)

    {[19659027]Actions action = new Actions(AppSession);

    action.SendKeys(text);

    action.Perform();

    }

Configuration des tests

Maintenant que notre TestBase est prête, nous pouvons passer à l'écriture de certains tests.

  1. Créez une nouvelle classe appelée MailAppTests ou simplement renommez celui par défaut—UnitTest1 fourni avec le modèle de projet de test unitaire.
  2. Ajoutez l'attribut [Test Class] à la classe. Il est obligatoire pour toute classe contenant des méthodes de test. De cette façon, vos tests seront visibles dans l'explorateur de tests.
  3. Vous vous souvenez comment nous avons créé la méthode Initialize() dans notre classe TestsBase  ? Voici venu le temps de l'utiliser. Et parce que nous avons besoin d'autres méthodes de cette même classe (MailAppTests), elle devrait dériver de la classe TestsBase .

    [TestClass]

    public class MailAppTests : TestsBase

    {

    [TestInitialize]

    public void TestInitialize()

    {

    this.Initialize();

    }

    . . .

    }

  4. Malgré l'attribut [TestClass] vous devriez vous familiariser avec quelques autres :

    • [TestInitialize] – appelé avant chaque test
    • [TestCleanup] – appelé après la fin d'un test
    • [ClassCleanup] – appelé une fois que tous les tests d'une classe ont été exécutés

    Notez comment nous appelons également les méthodes Cleanup() et StopWinappDriver() de notre classe de base.

    [TestClass]

    public class MailAppTests : TestsBase

    {

    [TestInitialize]

    public void TestInitialize()

    {

    this .Initialize ();

    }

    [TestCleanup]

    public void TestCleanup ()

    {

    this [19659032].Cleanup();

    }

    [ClassCleanup]

    public static void ClassCleanusp()

    {

    StopWinappDriver();

    }

  5. Nous devons également marquer nos méthodes comme des tests exécutables. Pour cela, il y a un autre attribut nommé [TestMethod] qui devrait être ajouté avec chaque méthode de test que nous créons.

Nos tests devraient être capables de localiser les éléments afin que nous puissions réagir avec eux. UI Recorder est un outil open-source permettant de sélectionner des éléments d'interface utilisateur et d'afficher les données de leurs attributs. Vous pouvez trouver l'outil dans le code source de WinAppDriver téléchargé plus tôt au début de cet article. Il se trouve dans le dossier ...WinappDriverToolsUIRecorder . Ouvrez et exécutez simplement la solution. Vous pouvez maintenant sélectionner les éléments dont vous avez besoin et utiliser leurs attributs en cliquant sur le bouton «Enregistrer» et en survolant l'élément cible.

 WAD UI Recorders montre l'interface utilisateur enregistrée avec Pause, Clear, XPath Ready.

]Une façon de rechercher des éléments consiste à utiliser la méthode FindElementsByXPath(string XPath) de la session, qui prend la chaîne XPath comme paramètre. Le XPath peut être utilisé à l'aide de l'outil UI Recorder.

Une autre approche plus rapide et plus pratique si possible consiste à utiliser la méthode FindElementByAccessibilityId (string automationID) également exposée par la session. Le AccessibilityID est l'identifiant attribué aux éléments dans notre application de test. Il peut être appliqué à l'aide de la propriété jointe AutomationProperties.AutomationId . Par exemple :

<telerik:RadRibbonButton Text="Reply"

LargeImage[19659032]="..ImagesReply.png"

Commande="{ Binding ReplyCommand}"

Taille="Large"

CollapseToSmall="WhenGroupIsMedium"

telerik : ScreenTip.Title="Répondre"

telerik:ScreenTip.Description=" Répondez à l'expéditeur de ce message."

telerik:KeyTipService.AccessText="R"

AutomationProperties.AutomationId = "buttonReply" />

Pour notre commodité et pour la lisibilité du code, nous créons une autre classe nommée TestsBaseExtensions . Le but de cette classe est de conserver en un seul endroit toute la logique dont nous avons besoin pour localiser nos éléments.

Une autre façon de trouver des éléments consiste à utiliser leur nom - FindElementByName (string elementName) où vous passez le nom de l'élément sous forme de chaîne.

Ecrire plusieurs tests

Notre premier test va vérifiez que les champs email d'un email sélectionné sont correctement remplis.

[TestMethod]

public void AssureEmailFieldsAreFilledInTest()

{

string replyTo = "SethBarley@telerikdomain.es";

string replyCC = "SethCavins@telerikdomain.uk";

string subject = "RE : Faisons une fête pour le nouvel an";

this.GetButtonReply( ).Cliquez sur();

Thread.Sleep (1000);

Assert.AreEqual (replyTo, this .GetFieldReplyTo () .Text);

Assert.AreEqual (replyCC, this .GetFieldReplyCc (). Text);

Assert.AreEqual (subject, this .GetFieldSubject (). Text);

}

Comme vous le voyez, nous avons la méthode GetButtonReply() effectuant l'action Click() et plusieurs champs qui sont ensuite vérifiés à l'aide du Assert class.

public static class TestsBaseExtensions

{

private const string Bu ttonReplydId = "buttonReply";

. . . . .

public static WindowsElement GetButtonReply(this TestsBase testsBase)

{

retourne testsBase .AppSession.FindElementByAccessibilityId(ButtonReplydId);

}

L'utilisation de XPath peut être plus délicate lorsque vous avez des éléments qui correspondent au même chemin. Dans de tels cas, l'utilisation de FindElementsByXPath est utile comme dans le code ci-dessus. De cette façon, vous pouvez spécifier plus précisément l'élément que vous essayez de localiser.

private const string fieldsReplyToCcSubjectXPath = "/ Window [@Name="Inbox - Mark@telerikdomain.com - My Application"][@AutomationId="MyApplication"] / Custom [@ClassName="MailView"] / Custom [@ClassName="RadDocking"][@Name="Rad Docking"] / Custom [@ClassName="RadSplitContainer"][@Name="Rad Split Container"] / Tab [@ClassName="RadPaneGroup"][@Name="Rad Pane Group"] / Edit [@ClassName="TextBox"] ]";

public static WindowsElement GetFieldReplyTo(this TestsBase testsBase)

{

retourne testsBase.AppSession.FindElementsByXPath(fieldsReplyToCcSubjectXPath)[0];

[194590}][194590}][194590

Notre deuxième test consiste à répondre à un e-mail. La recherche et la localisation des éléments s'effectuent de la même manière que dans l'exemple précédent. Voyez comment les SelectAllText(), PerformDelete(), WriteText(string text) de notre classe parent TestsBase sont utilisés ici. Ils utilisent les Actions que nous avons mentionnées précédemment.

[TestMethod]

public void ReplyToAnEmailTest()

{

string textToWrite = "Écrire du texte ici...";[19659338]this.GetButtonReply().Click();

this.GetRichTextBoxReply().Click( );

ceci.SelectAllText();

this.PerformDelete();

this.WriteText(textToWrite );

Assert.AreEqual(textToWrite, this.GetRichTextBoxReply().Text);

th is.GetButtonSendEmail().Click();

Assert.AreEqual(@"Envoi de la commande exécutée."this.GetElementByName(@"Send's commande exécutée.").Text);

this.GetElementByName("OK").Click();

}

Je voudrais attirer votre attention sur la méthode GetElementByName(string name). Après avoir cliqué sur le bouton Envoyer un e-mail une boîte de dialogue qui ne fait pas partie de la même arborescence visuelle apparaît à l'écran. Pour obtenir cette boîte de dialogue et trouver l'élément, nous essayons d'abord de trouver l'élément à l'aide de la AppSession mais, si cela échoue, nous utilisons la DesktopSession de la classe de base. Comme vous vous en souvenez probablement, la DesktopSession utilise l'ensemble de l'arborescence visuelle du bureau pour trouver l'élément.

public static WindowsElement GetElementByName(this TestsBase testsBase, string elementName)

{[19659002] try

{[19659002] return testsBase.AppSession.FindElementByName(elementName);

}

capture

{

Logger.LogMessage(" L'élément n'a pas été trouvé à l'aide de l'AppSession. Tentative de localisation de l'élément en utilisant DesktopSession."[19659032]);

}

return testsBase.DesktopSession.FindElementByName(elementName);

}

Dans le troisième et dernier test de notre projet de test, nous vérifions que les e-mails sont correctement marqués comme lus.

[TestMethod]

public void MarkMessageAsReadTest ()

{

this.GetTabUnreadEmail().Click();

this.GetUnreadEmailCellByFromAddress("SethCavins@ telerikdomain.uk").Cliquez sur ();

this.GetUnreadEmailCellByFromAddress("JimmieFields@ telerikdomain.eu").Cliquez sur ();[19659341]Assert.AreEqual("[31]"this.GetUInboxUnreadMessagesCount().Text);

}[19659351]

Résumé

Dans cet article, nous avons pu couvrir :

  • Que sont Appium et WinAppDriver
  • Comment créer un projet de test et de mettre en place un environnement de test
  • Différentes approches pour localiser des éléments d'interface utilisateur
  • Comment extraire le XPath d'un élément à l'aide de l'outil UI Recorder
  • Rédaction de plusieurs tests démontrant une petite partie de Les capacités d'Appium.

N'hésitez pas à télécharger et à explorer l'application de démonstration complète et le projet de test sur lequel nous avons travaillé. J'espère que cette procédure pas à pas vous aidera à démarrer avec l'automatisation de vos applications WPF à l'aide de Appium et WinAppDriver. Tous les commentaires ou commentaires sur le sujet sont plus que bienvenus.




Source link