Большой пласт работы с тестами UI составляют Desktop приложения под Windows. В разных статьях во время написания карт пользовательского интерфейса (PageObject’s) читателю показывают написание локаторов вручную с помощью UISpy.
Пять лет назад количество таких элементов в моих тестах стало слишком велико, контролы стали сложнее, а библиотеки для UI тестирования начали расти как грибы.
Рутину по поиску необходимого XPath было решено преобразовать в радость.
Вначале использовал Visual Studio UIMap Editor: чем сложнее были приложения, тем меньше он меня не устраивал в плане скорости и подстановки локаторов. Причины опишу в отдельной статье по UIAutomation и его обертках (TestStack.White, Cuite, Microsoft UITest и т.д.).
Итак, задача
Сделать простой редактор PageObject’s. Вспомогательные инструменты: UIAVerify.
Общие принципы
- каждый контрол (Control) рабочего стола обладает поисковыми свойствами и может содержать дочерние элементы
- контролы группируются в элементы (Element), элементы группируются в пространства имен (Assemblies)
- Инкапсуляция, наследование, полиморфизм
- Возможность использовать уже готовые карты. Например, у меня есть уже готовые карты и расширения для DevExpress, AvalonDock, OpenFileDialog и т.д. Я их переношу между проектами
Что получилось
На примере сложения в калькуляторе Windows 10:
- Составляю карту для окна «Калькулятор», для этого в редакторе карт из дерева рабочего стола переношу все объекты окна, и убираю лишнее. Можно добавлять элементы и вручную (например, для Selenium), полет фантазии безграничен
- Смотрю на сгенерированные названия элементов. Если они мне не нравятся, переименовываю вручную
- Сохраняю карту для обертки UIAutomation (Обычный конвертер XML => C#. Обертка может использоваться любая, Selenium, MS UITest, TestStack.White)
Время на все: минуты три
Справа – аналог дерева рабочего стола UIAVerify. Слева: карта
Результат
Под версионный контроль отправляется 4 файла:
<?xml version="1.0" encoding="utf-8"?> <Map Version="2.0.0.0" Uid="7b797972-8c3c-4dbf-9c30-7cc8ae14afda"> <Assembly Name="Calc" FrameWork="NavyWindows"> <Assembly Name="Map" FrameWork="NavyWindows"> <Element ControlType="Window" Name="Калькулятор" Comment="Window "Калькулятор""> <Control Comment="Window "TitleBar"" IsHidden="true" Name="Калькулятор" ControlType="Window"> <Property Name="Name">Калькулятор</Property> <Control Comment="Button "Close"" Name="ЗакрытьКалькулятор" ControlType="Button"> <Property Name="AutomationId">Close</Property> </Control> ... </Map>
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<UIКалькуляторWindow>(XPath); } } public static By XPath { get { return By.Xpath("Name=Калькулятор"); } } /// <summary> /// Button "plusButton" /// </summary> public UIButton UIПлюсButton { get { return Get<UIButton>(By.Xpath(@"AutomationId=plusButton")); } } ... </Map>
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); } } }
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(); } } }
Думаю, альтернативных решений уже много, ссылки и более удачные примеры кидайте в комментариях.
Спасибо за внимание!
ссылка на оригинал статьи https://habrahabr.ru/post/325058/
Добавить комментарий