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.
Prérequis
- 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.
- Activer Mode développeur pour Windows en tapant « pour les développeurs» dans le menu Démarrer, puis activez la fonction.
- Installez le Windows Application Driver .
- Download ] le code source WinAppDriver pour que vous puissiez bénéficier de l'outil UI Recorder .
Configuration du projet de test
- 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.
- 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.
- Sélectionnez nuget.org comme source du package et installez le Appium.WebDriver NuGet.
Base Class and Tests Session
- Créez une nouvelle classe appelée TestsBase où tous les paramètres Appium et le l'initialisation de la session sera décrite.
- 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.
- 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.
- 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();
}
- 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();
}
}
}
- 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.
- 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.
- 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.
- 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();
}
. . .
}
- 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();
}
- 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.
]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