Automated UI testing of a UWP app using Appium

Yassine Benabbas
7 min readMay 1, 2016

--

It’s like your screen having hands :)

Automated UI test of mobile applications can be already achieved on platforms other than UWP using Appium. UI testing using Appium works by interacting with the application using a WebDriver which executes our test scenarios.
On the 2016 edition of the build conference, Microsoft released a driver called the Windows Application driver (https://channel9.msdn.com/events/Build/2016/P499), making UWP apps compatible with Appium.
This post shows how to write UI tests for a UWP application using the Windows Application Driver.

How it works?

Performing automated UI tests using Appium requires three elements:

  1. The app that we want to test, we will call it the main app.
  2. The app that contains the tests scenarios. We will call it the UI test app.
  3. The driver that allows to communicate the UI test app and the main app.
Automated UI test model

The UI Test Automation flow will be like this:

  1. The user installs the main app
  2. The user starts the driver
  3. The user runs the UI test app
  4. The UI test app asks the driver to start the app
  5. The UI test app asks the driver to send clicks or other actions to certain UI elements
  6. The UI test app verifies the value of some UI elements

The advantage of this mechanism is that the test app can be written in a language other than C#. Appium supports any selenium language. In following, we will code both the main app and test app in C#.

Tutorial: creating and executing automated UI tests

The windows application driver

The Windows Application Driver is a application that allows the app to communicate with th main app. The project is available on github https://github.com/Microsoft/WinAppDriver.

The driver can be installed using the setup provided in this link: http://download.microsoft.com/download/6/8/7/687DEE85-E907-4A95-8035-8BC969B9EA95/WindowsApplicationDriver.msi.

The driver needs to be running before running the UI test app. To start it, simply run the program “WinAppDriver.exe” in C:\Program Files (x86)\Windows Application Driver.

The main application

The application that we want to test is a standard UWP application. There is however an additional aspect to consider with regard to UI testing. The test app needs to get a reference to elements that it wants to interact with. In order to achieve that, it can request the driver for an element by its title, type or by its accessibility identifier. The best solution here is to define accessibility identifiers to UI elements because they act as unique identifiers. It can be set in XAML using this property AutomationProperties.AutomationId.

Our sample main app contains a single page that has a “+” button and a text block that shows a number. When we press the “+” button, the number in the text block is incremented.

We will define the AutomationProperties.AutomationId of “btn_plus” and “result” to the button and the text block respectively.

Here is the XAML code:

<StackPanel Orientation=”Vertical” Background=”{ThemeResource ApplicationPageBackgroundThemeBrush}”>
<Button HorizontalAlignment=”Center” Content=”+” AutomationProperties.AutomationId=”btn_plus” Click=”Button_Click” />
<TextBlock Name=”textBlock” HorizontalAlignment=”Center” TextAlignment=”Center” AutomationProperties.AutomationId=”result” />
</StackPanel>

The code behind updates the the text block when we click on the + button

public int currentValue { get; set; }
private void Button_Click(object sender, RoutedEventArgs e)
{
currentValue = currentValue + 1;
textBlock.Text = “” + currentValue;
}

Please note that the attribution of accessibility identifiers is not necessary but simplifies the finding UI elements in the UI test app.

Screenshot of the main app. I clicked 4 times on the + button

The UI test application

The test application can be created as an independent solution using in any Selenium language. Let’s create a C# Unit test project, it is not necessary to create a Coded UI Test project.

Unit Test App

Then, add the following nugget packages.

  • Appium.WebDriver
  • Castle.Core
  • Selenium.Support
  • Selenium.WebDriver

These packages contain the API that allow to interact with the Windows Application Driver. Note that the API that we are going to use are different from the classic UWP apps.

Once completed, we can start writing our unit tests. In general, a test performs the following tasks:

  • Connect to driver and launch the main app
  • Send actions to UI elements
  • Verify the value of UI elements
  • Do some cleanup

I will describe below how to perform each task.

Connect to the main app

The first step here is to start the Windows Application Driver and keep it running. After a standard setup, it will located in C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe. The driver must keep running for he duration of the test session. The default listening address and port is 127.0.0.1:4723. It can be changed by running WinAppDriver.exe as administrator.

The Windows Application Driver is running

Next, let’s write the code that connects to the driver using its listening URL and launches the main app.

protected const string WindowsApplicationDriverUrl = “http://127.0.0.1:4723";
DesiredCapabilities appCapabilities = new DesiredCapabilities();
appCapabilities.SetCapability(“app”, “57b3a460–8843–4d84–822a-9f316274c2bf_tz6ph9wdjhqw8!App”);
IOSDriver<IOSElement> AppSession = new IOSDriver<IOSElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);

We generally put this code in the setup of test scenario so that we launch the main app only once. If you want to launch a new instance of the app for each test, you can call this code for every unit test.

The main classes here are the IOSDriver and IOSElement classes. The first one allows to interact with the main app through the driver. Its main purpose od to get a reference to UI elements of the main app. The second class interacts with individual UI elements of the main app.

Note here that we use the IOSDriver class in a windows context. While its name is weird, this class is very useful because it allows to find elements by their automation ID.

In the third line, we set a weird identifier for the “app” device capability. You need to replace this value with yours. It can be found the generated AppX\vs.appxrecipe file under RegisteredUserModeAppID node.

<RegisteredUserModeAppID>57b3a460–8843–4d84–822a-9f316274c2bf_tz6ph9wdjhqw8!App</RegisteredUserModeAppID>

If you build for x86 the vs.appxrecipe file will be located in (project)\bin\x86\Debug\AppX\vs.appxrecipe.

Send actions to UI elements

In order to send an action, we need to find the element and then call the corresponding action. In order to get a reference to an element, we user our AppSession’s FindElementByAccessibilityId method to find a UI element by its automation id. Since we have already set the automation id of both the button and text block of the main app. We only need the to use those values.

ButtonPlusElement = AppSession.FindElementByAccessibilityId(“btn_plus”) as IOSElement;
Assert.IsNotNull(ButtonPlusElement);
ButtonPlusElement.Click();

Verify the value of UI elements

Setting a value is as easy as sending an action.

RestultTextElement = AppSession.FindElementByAccessibilityId(“result”) as IOSElement;
Assert.IsNotNull(RestultTextElement);
Assert.AreEqual(“2”, RestultTextElement.Text);

Do some cleanup

The AppSession object is cleaned as follows

AppSession.Dispose();

Running the tests

Before running the tests the main app must either installed or launched from Visual studio.

Next, make sure that the Windows Application Driver is running.

Finally, open the test app solution in visual studio and choose the menu Test-Run-All Tests or Run All from the test explorer.

You will see super quickly that the main app opens, clicks on the + button and closes. The test results are synthesized in the Test explorer view.

Test explorer view

Here is some output from the Windows Application Driver window

==========================================
POST /session/C1A914E1-A57E-4AAE-9FFD-EE43E5B763CD/timeouts HTTP/1.1
Accept: application/json, image/png
Content-Length: 31
Content-Type: application/json;charset=utf-8
Host: 127.0.0.1:4723
{“type”:”implicit”,”ms”:2000.0}HTTP/1.1 200 OK
Content-Length: 63
Content-Type: application/json
{“sessionId”:”C1A914E1-A57E-4AAE-9FFD-EE43E5B763CD”,”status”:0}...

Here is the full code of the test class

namespace TestApp
{
[TestClass]
public class BasicScenarios
{
protected const string WindowsApplicationDriverUrl = “http://127.0.0.1:4723";
protected static IOSDriver<IOSElement> AppSession;
protected static IOSElement RestultTextElement;
protected static IOSElement ButtonPlusElement;
[ClassInitialize]
public static void Setup(TestContext context)
{
//Launch the app
DesiredCapabilities appCapabilities = new DesiredCapabilities();
appCapabilities.SetCapability(“app”, “57b3a460–8843–4d84–822a-9f316274c2bf_tz6ph9wdjhqw8!App”);
AppSession = new IOSDriver<IOSElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);
Assert.IsNotNull(AppSession);
AppSession.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(2));
//locate elements
ButtonPlusElement = AppSession.FindElementByAccessibilityId(“btn_plus”) as IOSElement;
Assert.IsNotNull(ButtonPlusElement);
ButtonPlusElement.Click();
ButtonPlusElement.Click();
RestultTextElement = AppSession.FindElementByAccessibilityId(“result”) as IOSElement;
Assert.IsNotNull(RestultTextElement);
}
[ClassCleanup]
public static void TearDown()
{
RestultTextElement = null;
AppSession.Dispose();
AppSession = null;
}
[TestMethod]
public void Case1()
{
Assert.AreEqual(“2”, RestultTextElement.Text);
}
[TestMethod]
public void Case2()
{
ButtonPlusElement.Click();
Assert.AreEqual(“2”, RestultTextElement.Text);
}
}
}

Conclusion

This post showed how to perform automated UI tests of a Universal Windows Platform app. We used the Windows Application Driver and a test app written in C#.

The source code is on github: https://github.com/yostane/UWP-Automated-UI-test-sample

--

--

Yassine Benabbas

Mobile app developer at Worldline, teacher and PhD. I love programming, videos games and manga. Trying hard to learn some Japanese.