Карты пользовательского интерфейса

от автора

Большой пласт работы с тестами 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:

  1. Составляю карту для окна «Калькулятор», для этого в редакторе карт из дерева рабочего стола переношу все объекты окна, и убираю лишнее. Можно добавлять элементы и вручную (например, для Selenium), полет фантазии безграничен
  2. Смотрю на сгенерированные названия элементов. Если они мне не нравятся, переименовываю вручную
  3. Сохраняю карту для обертки UIAutomation (Обычный конвертер XML => C#. Обертка может использоваться любая, Selenium, MS UITest, TestStack.White)

Время на все: минуты три

Справа – аналог дерева рабочего стола UIAVerify. Слева: карта

image

Результат

Под версионный контроль отправляется 4 файла:

Карта в XML

<?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> 

Сформированная карта для обертки 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<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> 

MapExt.cs и всевозможные расширения

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

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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *