Kolumne: XAML-Expertise

XAML-Tipp: UWP – Die neuen UI-Tests mit Microsoft Appium
Keine Kommentare

In der Kolumne „XAML Expertise“ präsentiert Gregor Biswanger Top-How-tos zum Thema XAML. Einsteiger und fortgeschrittene XAML-Experten sollen hier durch geballtes Wissen gesättigt werden. Heute gibt es die folgende Expertise: „UWP: Die neuen UI-Tests mit Microsoft Appium“

Das Microsoft UI Automation API ist seit Version 3.0 fester Bestandteil des .NET Frameworks. Unter der Projektvorlage „Coded UI Test Project“ lassen sich diese Tests über ein in Visual Studio integriertes Tool aufzeichnen; über MS Test Unit können Tests generiert werden. Der engen Bindung an das alte .NET Framework und der Abhängigkeit von MS-Test ist es geschuldet, dass Microsoft ein neues API entwickelt hat: Es heißt Appium und läuft über den im Web Stack bekannten Selenium-Treiber.

Das Appium API ist über eine REST-Schnittstelle verfügbar und soll mit seinem neuen Konzept als eine Alternative für zukünftige UI-Tests dienen. Any Language: Durch die REST-Schnittstelle können unterschiedliche Entwicklungssprachen darauf zugreifen. Any Test Runner: Die enge Bindung an das hauseigene MS-Test wurde gelöst. Unit-Test-Runner aus den unterschiedlichen Entwicklungsplattformen wie Node.js, Python und JUnit werden unterstützt. Any App: Nicht nur native Windows-10-Apps lassen sich automatisiert bedienen und testen, sondern Hybrid- und Webanwendungen ebenfalls. Any Platform: Hinzu kommt außerdem die Unterstützung für unterschiedliche Plattformen wie Android und iOS, was gerade für Xamarin-Entwickler von Interesse sein dürfte.

Für native Windows-10-Apps wird das Gesamtpaket über den Windows Application Driver bereitgestellt. Zum Ausführen der Tests muss nach der Installation der WAD-Dienst WinAppDriver.exe unter C:\Program Files (x86)\Windows Application Driver ausgeführt werden.

Die Testanwendung kann als eigenständige Lösung in jeder Selenium-Sprache erstellt werden. Um ein C#-Unit-Testprojekt zu erstellen, ist es nicht notwendig, ein Coded-UI-Test-Projekt zu erstellen. Fügen Sie dem Projekt die folgenden NugGet-Pakete hinzu: Appium.WebDriver, Schloss.Kore, Selenium.Support und Selenium.WebDriver. Diese APIs ermöglichen die Kommunikation mit dem Windows Application Driver. Im Allgemeinen führt ein Test die folgenden Aufgaben aus:

  • Die Verbindung zum Treiber wird hergestellt und die Hauptanwendung gestartet.
  • Die Aktionen werden an Benutzeroberflächenelemente gesendet.
  • Der Wert der UI-Elemente wird überprüft.
  • Instanzen werden aufgeräumt.

Für sich wiederholenden Schritte dient eine eigene Hilfsklasse. Listing 1 zeigt die Implementierung der CalculatorSession-Hilfsklasse, die für den Zugriff auf den Windows-10-Taschenrechner zuständig ist. Der Unit-Test selbst benötigt dann die CalculatorSession-Hilfsklasse als Basisklasse. In Listing 2 ist ein fertiger Unit-Test zu sehen, der die Addition von 1 und 7 ausführt und anschließend das Ergebnis überprüft. In Abbildung 1 wird das gesamte Szenario demonstriert.

Im Unit-Test sind die Buttonnamen fest eingetragen. Für eigene Windows-10-Apps in XAML dient das AutomationProperties.AutomationId-Property, um Namen festzulegen. Bei fremden Windows-Anwendungen hilft das Open-Source-Tool WinAppDriver UI Recorder.

using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium.Windows;
using OpenQA.Selenium.Remote;
using System;

namespace CalculatorTest
{
  public class CalculatorSession
  {
    // Note: append /wd/hub to the URL if you're directing the test at Appium
    private const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
      private const string CalculatorAppId = "Microsoft.WindowsCalculator_8wekyb3d8bbwe!App";

    protected static WindowsDriver<WindowsElement> session;

    public static void Setup(TestContext context)
    {
      // Launch Calculator application if it is not yet launched
      if (session == null)
      {
        // Create a new session to bring up an instance of the Calculator application
        // Note: Multiple calculator windows (instances) share the same process Id
        DesiredCapabilities appCapabilities = new DesiredCapabilities();
        appCapabilities.SetCapability("app", CalculatorAppId);
        appCapabilities.SetCapability("deviceName", "WindowsPC");
        session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);
        Assert.IsNotNull(session);

        // Set implicit timeout to 1.5 seconds to make element search to retry every 500 ms for at most three times
        session.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(1.5));
      }
    }

    public static void TearDown()
    {
      // Close the application and delete the session
      if (session != null)
      { 
        session.Quit();
        session = null;
      }
    }
  }
}
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium.Windows;
using System.Threading;
using System;

namespace CalculatorTest
{
  [TestClass]
  public class ScenarioStandard : CalculatorSession
  {
    private static WindowsElement header;
    private static WindowsElement calculatorResult;

    [TestMethod]
    public void Addition()
    {
      // Find the buttons by their names and click them in sequence to peform 1 + 7 = 8
      session.FindElementByName("One").Click();
      session.FindElementByName("Plus").Click();
      session.FindElementByName("Seven").Click();
      session.FindElementByName("Equals").Click();
      Assert.AreEqual("8", GetCalculatorResultText());
    }

    [ClassInitialize]
    public static void ClassInitialize(TestContext context)
    {
      // Create session to launch a Calculator window
      Setup(context);

      // Identify calculator mode by locating the header
      try
      {
        header = session.FindElementByAccessibilityId("Header");
      }
      catch
      {
        header = session.FindElementByAccessibilityId("ContentPresenter");
      }            

      // Ensure that calculator is in standard mode
      if (!header.Text.Equals("Standard", StringComparison.OrdinalIgnoreCase))
      {
        session.FindElementByAccessibilityId("NavButton").Click();
        Thread.Sleep(TimeSpan.FromSeconds(1));
        var splitViewPane = session.FindElementByClassName("SplitViewPane");
        splitViewPane.FindElementByName("Standard Calculator").Click();
        Thread.Sleep(TimeSpan.FromSeconds(1));
        Assert.IsTrue(header.Text.Equals("Standard", StringComparison.OrdinalIgnoreCase));
      }

      // Locate the calculatorResult element
      calculatorResult = session.FindElementByAccessibilityId("CalculatorResults");
      Assert.IsNotNull(calculatorResult);
    }

    [ClassCleanup]
    public static void ClassCleanup()
    {
        TearDown();
    }

    [TestInitialize]
    public void Clear()
    {
        session.FindElementByName("Clear").Click();
        Assert.AreEqual("0", GetCalculatorResultText());
    }

    private string GetCalculatorResultText()
    {
        return calculatorResult.Text.Replace("Display is", string.Empty).Trim();
    }
  }
}
Abb. 1: Die neuen UI-Tests mit Microsoft Appium

Abb. 1: Die neuen UI-Tests mit Microsoft Appium

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -