User interface cards

A large layer of working with UI tests is Desktop applications for Windows. In various articles, while writing user interface maps (PageObject's), the reader is shown manually spelling locators using UISpy.

Five years ago, the number of such elements in my tests became too large, controls became more complicated, and libraries for UI testing began to grow like mushrooms.

It was decided to convert the routine of finding the necessary XPath into joy.

At first I used Visual Studio UIMap Editor: the more complicated the applications, the less it didn’t suit me in terms of speed and locator substitution. I will describe the reasons in a separate article on UIAutomation and its wrappers (TestStack.White, Cuite, Microsoft UITest, etc.).

So the challenge


Make a simple PageObject's editor. Helper Tools: UIAVerify.

General principles


  • each control of the desktop has search properties and may contain child elements
  • controls are grouped into elements (Element), elements are grouped into namespaces (Assemblies)
  • Encapsulation, inheritance, polymorphism
  • The ability to use ready-made cards. For example, I have ready-made maps and extensions for DevExpress, AvalonDock, OpenFileDialog, etc. I transfer them between projects

What happened


Using the addition example in a Windows 10 calculator:

  1. I’m making a map for the “Calculator” window. To do this, in the map editor from the desktop tree I transfer all the window objects with one click and remove the excess. Locators are affixed automatically. You can add elements manually (for example, for Selenium), the flight of fantasy is unlimited
  2. I look at the generated element names. If I don’t like them, I rename them manually
  3. I save the map for the UIAutomation wrapper (Normal XML => C # converter. Any wrapper can be used, Selenium, MS UITest, TestStack.White)

Time for everything: about three minutes

On the right is an analog of the UIAVerify desktop tree. Left: map

image

Result


4 files are sent under version control:

Map in XML
КалькуляторClose
...


Formed wrapper card UIAutomation
namespace Calc
{
	public partial class UIКалькуляторWindow : UIWindow
	{
		public UIКалькуляторWindow(UIControl control) { Wrap(control); }
		public UIКалькуляторWindow() {  }
		public static UIКалькуляторWindow Instance 
		{ 
			get { return Desktop.Instance.Get(XPath); }
		}
		public static By XPath { get { return By.Xpath("Name=Калькулятор"); } }
		/// 
		/// Button "plusButton"
		/// 
		public UIButton UIПлюсButton
		{
		 	get { return Get(By.Xpath(@"AutomationId=plusButton")); }
		}
...



MapExt.cs and various extensions
namespace Calc
{
	public static class UIКалькуляторWindowExt
	{ 
        public static int Result(this UIКалькуляторWindow  window)
        {
            var textValue = window.UIResultText.Text
                .Replace("На экране показано", "")
                .Replace(" ", "");
            return int.Parse(textValue);
        }
	}
}


CalculationTests.cs Test
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Calc;
using System.Diagnostics;
using System;
namespace CalcTests
{
    [TestClass]
    public class CalculationTests : IDisposable
    {
        public CalculationTests()
        {
            _process = Process.Start("calc.exe");
            _calc = UIКалькуляторWindow.Instance;
        }
        [TestMethod]
        public void Sum()
        {
            _calc.UIОдинButton.Click();
            _calc.UIПлюсButton.Click();
            _calc.UIПятьButton.Click();
            _calc.UIРавноButton.Click();
            Assert.AreEqual(6, _calc.Result(), "Не совпадает результат");
        }
        public UIКалькуляторWindow _calc { get; set; }
        Process _process;
        public void Dispose()
        {
            _calc.Close();
        }
    }
}


I think there are already many alternative solutions, throw links and more successful examples in the comments.

Thanks for attention!

Also popular now: