In its release notes for Visual Studio 2019, Microsoft announced the end of life for Coded UI test.
OSS UI test tools such as Selenium and Appium have gained momentum and have a strong community backing. Because these frameworks have become industry standards, we deprecated Coded UI test for automated UI-driven functional testing. Visual Studio 2019 will be the final version of Visual Studio with Coded UI test features.
Microsoft recommends Appium with WinAppDriver for testing desktop and UWP apps, and this message has sparked the interest among our users: are DevExpress controls compatible with Appium? We have tested a number of our controls, and the short answer is - yes. Here’s what you should do to create automated UI tests with Appium.
Go to https://github.com/Microsoft/WinAppDriver/releases and download two applications.
- WinAppDriver - allows you to run tests. Requires installation.
- WinAppDriver UI Recorder - allows you to record tests at runtime. Does not require installation - unzip the downloaded archive to any folder.
Turn on Developer Mode within Windows.
Run WinAppDriver.exe as an administrator and leave it running. Note the address the application is listening to, you will need it later.
Open a Visual Studio solution that you want to test, or create a new sample solution.
Add a new Unit Test Project to the solution.
Right-click the Unit Test project in Solution Explorer and select “Manage NuGet Packages…”. Install the latest stable Appium.WebDriver package.
Open the
UnitTest1.cs
file of the Unit Test project and add two classes:MainDemoSession
(defines methods that start and finish test sessions) andHelper
(contains the method that finds tested UI elements). Use the address from step #3 as theWindowsApplicationDriverUrl
value.public class MainDemoSession { protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723"; private const string ApplicationPath = @"C:\Users\...\AppiumTest.exe"; protected static WindowsDriver<WindowsElement> desktopSession; public static void Setup(TestContext context) { // Launch a new instance of the tested application if (desktopSession == null) { // Create a new session to launch the tested application AppiumOptions options = new AppiumOptions(); options.AddAdditionalCapability("app", ApplicationPath); desktopSession = new WindowsDriver<WindowsElement>( new Uri(WindowsApplicationDriverUrl), options); Assert.IsNotNull(desktopSession); Assert.IsNotNull(desktopSession.SessionId); // Set implicit timeout to 1.5 seconds //to make element search to retry every 500 ms //for at most three times desktopSession.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1.5); } } public static void TearDown() { // Close the application and delete the session if (desktopSession != null) { desktopSession.Close(); desktopSession.Quit(); desktopSession = null; } } } public static class Helper { public static WindowsElement FindElementByAbsoluteXPath( this WindowsDriver<WindowsElement> desktopSession, string xPath, int nTryCount = 3) { WindowsElement uiTarget = null; while (nTryCount-- > 0) { try { uiTarget = desktopSession.FindElementByXPath(xPath); } catch { } if (uiTarget != null) { break; } else { System.Threading.Thread.Sleep(400); } } return uiTarget; } }
Modify the auto-generated
UnitTest1
class as follows:[TestClass] public class UnitTest1 : MainDemoSession { [TestMethod] public void TestMethod1() { //test start //test finish } [ClassInitialize] public static void ClassInitialize(TestContext context) { Setup(context); } [ClassCleanup] public static void ClassCleanup() { TearDown(); } }
Run your application, and (in case you have a multi-screen setup) drag it to the main system display.
Launch the WinAppDriver UI Recorder and click “Record”. Hover over the first UI element you want to interact with, and wait until it starts flashing blue. The Recorder’s status bar will change its text from “Active” to “XPath Ready”.
When the element is flashing, the recorder is ready and you can perform UI actions: click this element, drag it, enter new values, etc. After you are done with this element, hover over another UI element, wait for the recorder’s confirmation and repeat the process.
Once you have recorded a sequence of steps you wish to reproduce, click “Pause” within the recorder. You can open the actions selector to make certain that all UI actions have been recorded.
Click the “Generate and copy C# code to Clipboard” button to copy the code for all recorded actions. Paste this code into the
UnitTest1.TestMethod1
method. For instance, the code below selects the “Job” tab.[TestMethod] public void TestMethod1() { //test start // LeftClick on TabItem "Job" at (20,31) Console.WriteLine("LeftClick on TabItem \"Job\" at (20,31)"); string xpath_LeftClickTabItemJob_20_31 = "/Pane\[@ClassName=\"#32769\"\][@Name=\"Desktop 1\"]/Window\[starts-with(@AutomationId,\"XtraForm\")]/Pane[@Name=\"The XtraLayoutControl\"\][starts-with(@AutomationId,\"dataLayoutControl\")]/Table[@Name=\"Root\"]/Table[@Name=\"autoGeneratedGroup0\"]/Table[@Name=\"Root\"]/Table[@Name=\"Photo\"]/Table[@Name=\"FirstAndLastName\"]/Tab[@Name=\"Tabs\"]/TabItem[@Name=\"Job\"]"; var winElem_LeftClickTabItemJob_20_31 = desktopSession.FindElementByAbsoluteXPath(xpath_LeftClickTabItemJob_20_31); if (winElem_LeftClickTabItemJob_20_31 != null) { winElem_LeftClickTabItemJob_20_31.Click(); } else { Console.WriteLine($"Failed to find element using xpath: {xpath_LeftClickTabItemJob_20_31}"); return; } //test finish }
During internal testing, we observed that auto-generated code may fail to locate the UI element by its full path:
/Pane\[@ClassName=\"#32769\"\][@Name=\"Desktop 1\"]/Window[starts-with…
If this happens, shorten all element paths so that they begin with “/Window”.
string xpath_LeftClickTabItemJob_20_31 = "/Window[starts-with(@AutomationId...";
Additionally, you can use Assert.Fail instead of Console.WriteLine to debug the test (should it fail to locate a UI element).
Assert.Fail($"Failed to find element...");
Right-click the Unit Test project in Visual Studio and click “Run Tests”. The test will launch your application, repeat all recorded steps, and close the application afterwards. All test activity is logged in the WinAppDriver console launched in step #3.
You can launch Appium tests in much the same way as Coded UI. The only difference is that you need the WinAppDriver running on your test execution machine.
Tell us what you think
With Microsoft's decision to deprecate Coded UI support, what is the future of automated UI tests for you and your enterprise? How many UI automation tests your current project has? Will you migrate them to Appium, or will you switch from UI automation in favor of more unit tests?