Author : Edwin Hernandez Maynez
This article is a follow up on a previous post titled "UI Automation - Page Object Model and other Design Patterns" and is part of a series of posts related to UI Test automation, if you are interested in UI automation tools in general, we definitely recommend checking out our earlier post: "What are the best UI Test Automation Tools?" which was published on this same blog not so long ago. You may want to have a look at those two articles since it provides a high level view of what tools are available in the market for Functional UI Test automation, either for Web, Mobile or Desktop and then a deeper analysis of code design approaches.
In this article I will describe broadly the technical highlights of how Desktop UI automation is done and I will describe the main features of a relatively new test framework that is becoming a must-use for UI automation for Windows-based applications.
About CodedUI
CodedUI is a Microsoft technology created to provide support of Desktop and Web UI automation, this technology is now deprecated and Visual Studio 2019 is the last version of VS that will include it. Microsoft has announced that it recommends the following technologies as replacements:
- We recommend using Selenium for testing web apps
- Appium with WinAppDriver for testing desktop and UWP apps
- Consider Xamarin.UITest for testing iOS and Android apps using the NUnit test framework.
From <https://docs.microsoft.com/en-us/visualstudio/test/use-ui-automation-to-test-your-code?view=vs-2019
Given that announcement, if you have an interest or a need to be able to provide Desktop UI automation support for one of your projects, please read forward as I list the main features of WinAppDriver.
Windows Application Driver
WinAppDriver is a test framework developed by Microsoft as an open source project, it's an implementation of Appium which is primarily a Mobile App framework, itself based on Selenium. Therefore WinAppDriver is a Selenium-like automation framework. This project is combining the best of two worlds, on one hand it encapsulates most of the technology of the now deprecated CodedUI and it fuses it with the flexibility, easiness of use and adoption of Selenium.
Just like Selenium, WinAppDriver is a set of libraries that can be integrated into any Test Runner that supports Appium. E.g. WinAppDriver scripts can be developed and executed with MSTest from Visual Studio.
Requirements
- WinAppDriver only runs on Windows 10
- You will need a test runner, such as MSTest with Visual Studio, but any other Appium Test Runner would do
Where can you get it:
- Download and Install the latest release (v1.1 now): https://github.com/microsoft/WinAppDriver/releases/tag/v1.1
- Enable Developer Mode on your Windows 10 PC
Desktop UI Automation
Unlike Web UI automation, when working with Desktop applications, there is more variance on the technologies that could have been used to develop the application you are testing. This has an impact in the toolset's ability to identify and perform actions on a given UI element:
- UWP – Universal Windows Platform, also known as Universal Apps or Modern Apps, It's Microsoft’s latest desktop application technology. It's XAML based. Only runs on Windows 10 machines
- WPF - also XAML based, much more mature, runs on any Windows version and has been around since 2006.
- WinForms - one of the older technologies, now found mostly on legacy applications.
- MFC/Classic Windows - MFC is a UI library normally paired with Win32 applications. This option is normally chosen when more efficiency is needed with low-level C++ handling or when supporting non-Microsoft platforms.
From <https://docs.microsoft.com/en-us/windows/apps/desktop/choose-your-platform>
CodedUI is an umbrella framework for Web and Desktop UI technologies:
UI Automation (UIA) and Microsoft Active Accessibility (MSAA) are two lower-level accessibility technologies used to provide access to UI elements. MSAA is now a legacy library while UIA is newer and more capable. UIA is an accessibility framework not a test framework and it is not meant to be used as such.
Both of these technologies are now under the hood of WinAppDriver, which is why WinAppDriver fully supports the desktop technologies listed above (UWP,WPF,Winforms & MFC).
How to get started
I will provide a quick start guide and simple scripts on Visual Studio 2019:
- First follow the instructions above to download and install WinAppDriver, then
- Create a Unit Test Project in Visual Studio
- Go to Manage Nuget Packages, then Browse for Appium.WebDriver.
- Install it, it will automatically add a few more packages such as Selenium.WebDriver
- If it doesn't pull them automatically, you may have to search for them and install them yourself.
- It should look like this on the end:
-
- Now that you have that setup: the driver configuration differs depending on which kind of application you are testing. You can find below the setup for a non-UWP (classic app) and a UWP app. These two examples have the minimal code needed for a WinAppDriver test:
using System;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium.Windows;
using OpenQA.Selenium.Remote;
namespace Blog
{
[TestClass]
public class UITests
{
[TestMethod]
public void SysInfoTest()
{
Process.Start(@"C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe");
WindowsDriver<WindowsElement> SysInfoApp;
DesiredCapabilities appCapabilities = new DesiredCapabilities();
appCapabilities.SetCapability("app", @"C:\Windows\System32\msinfo32.exe");
SysInfoApp = new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), appCapabilities);
SysInfoApp.FindElementByName("Help").Click();
SysInfoApp.FindElementByName("About System Info...").Click();
}
[TestMethod]
public void CalculatorTest()
{
Process.Start(@"C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe");
WindowsDriver<WindowsElement> Calculator;
DesiredCapabilities appCapabilities = new DesiredCapabilities();
appCapabilities.SetCapability("app", "Microsoft.WindowsCalculator_8wekyb3d8bbwe!App");
Calculator = new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), appCapabilities);
Calculator.FindElementByAccessibilityId("num5Button").Click();
Calculator.FindElementByAccessibilityId("plusButton").Click();
Calculator.FindElementByAccessibilityId("num3Button").Click();
Calculator.FindElementByAccessibilityId("equalButton").Click();
}
}
}
- Similarly to Selenium, in WinAppDriver, elements are found by providing identifiable properties such as Class, Id, Name, AccessibilityID, Xpath, etc. You can spy these properties using a few other tools such as:
- WinAppDriver Recorder, compact app provided by the same team, gives you an Xpath to the element you need.
- Inspect.exe, powerful tool that comes with the Microsoft SDK, it also provides pattern recognition for UIA accessibility. Use the properties listed for a given element to find it with WinAppDriver.
- Spy++. An object identification tool that comes with Visual Studio.
- That should be it, now you have a fully-working WinAppDriver test framework. It may sound easy to get started but the challenge on UI automation is not on the initial setup but on the maintainability, good coding practices and the feasibility of the framework to identify all the UI elements that you will need. Here are some pointers:
Tips and Tricks
- Depending on the Desktop development technology that was used to create the app you are testing, and depending on whenever or not the developers chose to use the out-of-the box UI elements or chose to customize them, finding elements can be a piece of cake or a real pain.
- Even if the developers used the standard UI elements, if they are not including an UIAutomation property or if they are leaving properties like name/text blank or the same for different elements…then identifying elements can be challenging.
- My recommendation here is to use xpath to its full extent: look into functions such as contains(), last(), first(), sibling(), etc. … find how to go up or down levels on the xpath tree to navigate to the element you need out of another one. You can also use WinAppDriver findElements method to pull all matching elements into a Collection and just iterate thru it until you find the one you need.
- You may find that WinAppDriver just as CodedUI, may not be able to inspect or drill down into certain elements, especially when these elements are customized or on certain corner cases of the older technologies (Winforms or MFC). In this case you may need to dive into using UIA patterns to find and perform actions into these elements.
- Maintainability and fragility of UI scripts to changes really becomes an issue as your project grows. Look into Design Patterns such as Page-Object-Model (I just wrote an article about this, you can find a link to it at the top of this page)