Разделы портала

Онлайн-тренинги

.
Как автоматизировать тестирование на desktop
22.11.2018 12:21

Автор: WaveAccess

Оригинальная публикация

Часть 1: "Do Pilot" или платные фреймворки

Если вы сталкивались с автоматизацией тестирования, то это, скорее всего, были автотесты для web-страницы, web-блога, web-интерфейса. Возможно, ваша команда использует Appium для функционального тестирования мобильного приложения или инструментальные тесты Android (Espresso).

Но в 2018 году всё ещё нужно разрабатывать десктопные приложения, поддерживать legacy-проекты. Банки, финансовые отделы компаний, производства и лаборатории, сегмент HoReCa применяют Windows Desktop-приложения. Множество бизнесов разных направлений применяют их для учета, организации и автоматизации бизнес-процессов.

Пользовательская машина дает не меньше возможностей, чем web. А иногда и больше. Например, это работа с локальными файлами и устройствами: обработка больших данных, возможность использовать специфичное оборудование, обращаться к различным сервисам. Причин для сохранения десктопных приложения масса:

  • Подключение внешних устройств. К примеру, использование сканера отпечатков пальцев для идентификации, сканера паспорта и других устройств.
  • Соблюдение политики безопасности. Например, на заводе или в банке, где запрещен выход в Internet.
  • Уже существующий парк машин, который может состоять, например, из PС на OC Windows 7.

Всё вышеперечисленное — потребности реальных заказчиков, и достижения web для таких задач неприменимы.

Тестирование — это долгие месяцы? Стратегия Do Pilot

Наш заказчик использует desktop-приложение (.NET) для делопроизводства, организации и сопровождения бизнес-процессов, которое разрабатывается и развивается годами.

Сейчас оно состоит из десятков тысяч строк кода, а это сотни тестов и примерно полтора месяца, которые требуются на первичное ручное тестирование:  

  • Две недели на первичный ручной прогон регресс тестов. 

  • Две недели на повторный прогон.  

  • Время на исправление ошибок и возможные накладки.

По мере исправления ошибок затрачиваемое время растет, могут случаться накладки во время планирования и контроля. Итого — примерно 1,5 месяца работы двоих инженеров, которые обычно задействованы на выполнении регрессионных проверок.

Полквартала для завода, производства или банка, когда нужно срочно доработать функционал, внести правку, добавить модуль, оборачиваются потерей денег.  

Заказчику нужны быстрые релизные итерации: запрос, разработка, короткое тестирование и внедрение. Главное — оставить качество на прежнем уровне, а лучше — повысить его по объективным количественным критериям. Именно так появляется необходимость автоматизации тестирования.

Конечно, не все в тестировании можно автоматизировать, и некоторые задачи все еще приходится делать вручную. Но если нужно узнать, насколько автоматизация возможна, полезна и пригодна на конкретном проекте, — команда WaveAccess пользуется manage-паттерном автотестирования “Do Pilot” (“создай пилотную версию”).  

Стратегия Do Pilot заключается в том, чтобы автоматизировать часть работ и оценить их результат: потраченное время, масштабируемость тестов, стоимость их поддержки. То есть, сделать пилотную версию автотеста (АТ), а затем принять решение о том, стоит ли переводить всё тестирование в автоматизацию.

Всегда проще потратить пару недель, чтобы понять: найден полезный инструмент, пригодный для бизнеса, или это потеря времени.

Do Pilot на проектах WaveAccess: требования и возможности  

Итак, мы решили реализовать пилотную версию АТ для крупного.NET Windows Desktop приложения нашего клиента. Для этого выбрали стабильную версию приложения и подобрали шесть основных тестовых сценариев, отмеченных тегом Smoke или Regress, прохождение которых даёт гарантию, что основной функционал тестируемого приложения работает в соответствии с техническим заданием.

К результату выдвинули требования:

  • Оперативность. Имеется возможность “на выходе” просматривать отчеты из CI (Continuous Integration) с ночными прогонами этих 6-ти тестов или получать письмо с описанием “упавших” тестов.

  • Прозрачность. Команда тестирования понимает, что именно проверяется в каждом шаге теста, а менеджер может читать отчет, написанный в понятной для него форме (например, "на окне n не хватает третьего поля ввода").

  • Стоимость. Выбранный инструмент не удорожает проект без необходимости.

Главный вопрос, который встал перед нами, — поиск подходящего инструмента для написания АТ, который отвечал бы всем критериям.

Обзор решений для автотестирования 

Как мы уже сказали выше: web- и mobile-технологиях автотестирование сейчас преобладает. Рассмотрим, что же, все-таки, можно найти на этом поле для Windows Desktop.  

Платные инструменты. TestComplete

Одним из лидеров платных фреймворков является полноценная студия для АТ TestComplete от SmartBear. У решения есть триал-период, есть положительные отзывы пользователей.

Выбираем решение "из коробки" на одного пользователя:


Выбираем кастомизированное решение, убираем "Web" и "Mobile".


Пытаемся максимально снизить цену. За возможность безлимитного тестирования и другие необходимые аддоны все же придется доплатить 1700 для одной лицензии.

Научить команду тестирования пользоваться студией TestComplete можно, получив сертификаты по 150-700 за каждый. Возьмём один базовый TestComplete Certification

Итого:


Итак, 4000 за студию и один год поддержки на 1 пользователя. Однако заказчику мы хотели предложить такое решение, которое при сохранении качества платных решений “из коробки” не вынуждало бы его платить такую сумму нам, а через год — продолжать платить уже за продление лицензии.

Платные инструменты. Telerik Test Studio

Следующий платный инструмент — Telerik Test Studio. Его цены:


Но за каждую вспомогательную функцию придется платить:


Эта сумма — 2499 + 899 +599 = 4000$ — включает только одного пользователя и год поддержки. Умножив ее на количество пользователей, а на данном проекте команда WaveAccess состояла из двух инженеров, получаем итоговую цену: 8000$ за год. И многие другие платные фреймворки также удивляют ценообразованием.  

Вывод по рассмотренным фреймворкам 

Мы  стремимся к оптимизации ресурсов при сохранении качества. Но главное — мы стремимся к тому, чтобы до конца понять: что именно мы предлагаем клиенту, как используем. Поэтому ПО с открытым программным кодом предпочтительнее, чем коробочное решение — этакий “кот в мешке”.

Часть II: Обзор фреймворков с открытым кодом


Автотестирование активно развивается для web- и mobile-проектов. Но десктопные приложения приходится тестировать до сих пор: их по-прежнему используют финансовые компании, производства, сегмент HoReCa. Зайдите в ближайший банк, кафе, ресторан - всюду вы увидите Windows Desktop. При этом тестирование таких приложений почти не развивается, информации о нем мало.  

Эта статья написана по опыту одного из наших проектов: необходимо было тестирование Windows Desktop приложения с десятками тысяч строк кода. Ручная проверка подобного решения заняла бы слишком много времени, поэтому мы решили разработать пилотную версию автотестов для выполнения проекта.

Подбирая инструмент для этой задачи, мы столкнулись с тем, что функции коммерческих студий  ориентированы, в основном, на web- и mobile-, сами решения неоправданно удорожают проект, и не до конца понятно, что у них "под капотом". Мы стремимся к тому, чтобы до конца понять: что именно мы предлагаем клиенту, как используем, поэтому обратились к поиску инструментов с открытым кодом и выбрали оптимальный.  

Итак, нашей задачей было создать пилотную версию АТ (автотестов). Конечной целью — автоматизация тестирования сложного .NET desktop приложения. При подборе инструмента выдвигали следующие требования:

  • Оперативность. Возможность "на выходе" просматривать отчеты из CI с ночными прогонами этих шести тестов (или получать письмо с описанием “упавших” тестов).

  • Прозрачность. Нужно, чтобы команда тестирования понимала, что именно  проверяется в каждом шаге теста, а менеджер мог читать отчет в понятной для него форме (например: "на окне n не хватает третьего поля ввода").

  • Стоимость. Необходим инструмент, который не удорожает проект без необходимости.  

Сравнение бесплатных фреймворков

Первым решением, опробованным для наших задач, стал Visual Studio Coded UI.

Плюсы:

  1. Те же технологии в тестировании, что и в разработке продукта.

  2. Есть test recorder.

  3. Работа с WinForms.

  4. Работа с UI-контролами DevExpress.

Минусы:

  1. Небольшой объем документации.

  2. Платная VS.

  3. Test recorder генерирует плохо поддерживаемый код: тесты после записи и запуска сразу “падают” (возможно, не воспроизводится на “простых” интерфейсах).

  4. BDD-написание тест-кейсов (с использованием, например, одного из самых популярных фреймворков на языке C# — Specflow) несовместимо “из коробки” с Coded UI.

  5. Ограничения поиска и работы с элементами пользовательского интерфейса, накладываемые UIA API v.1 — MSAA. 

Фреймворк CUITe может использоваться в дополнение к инструменту Coded UI под разные версии VS. Можно взять инструмент на заметку, но серьезных недостатков Coded UI он не исправляет.

Фреймворк TestStack.White — второе бесплатное решение, которое мы рассмотрели.

Плюсы:

  1. Инструмент для полноценного написания тестов на языке C#.

  2. Совместим с фреймворками BDD.

  3. MSAA, UIA 2, 3 — на выбор.

Минусы:

  1. “Заброшенная” кодовая база явно нуждается в рефакторинге.  

  2. Апдейт Nuget пакета не проходил с 2014 года, но в репозитории есть изменения.

Дальнейший поиск привел команду к фреймворку WhiteSharp.

Плюсы:

  1. Инструмент для полноценного написания тестов на языке С#.

  2. Совместим с фреймворками BDD.

Минусы:

  1. Нет возможности нормально идентифицировать все элементы UI. Не подходит к DevExpress элементам.

  2. Апдейт Nuget-пакета не происходил с 2016 года.

  3. Немного документации, небольшое комьюнити.

  4. Медленное исполнение элементарных кейсов (“открыть приложение”, “проверить содержимое строки статуса”)

У Winium.Desktop оказался большой минус — отсутствие поддержки с .NET 4.0 

FlaUI — инструмент для полноценного написания тестов на языке С#. Автор подчеркивает, что он хотел переписать с чистого листа TestStack.White, убрав ненужное и устаревшее.

Плюсы:

  1. Совместим с фреймворками BDD

  2. Возможность использовать любую версию UIA: MSAA, UIA2 и UIA3

  3. Поддерживаемая версия ОС Windows 7, 8, 10 (XP, скорее всего тоже, но мы не пробовали).

  4. Хорошее комьюнити: решение проблем не только в issues, но и в чатах.

 WinAppDriver + Appium — инструмент для полноценного написания тестов на языках разработки: C#, Java, Python.

Плюсы:

  1. Разработан и поддерживается Microsoft.

  2. Совместим с фреймворками BDD.

  3. Невысокий порог вхождения, если был опыт написания тестов для веба или мобильных платформ.

Минусы:

  1. Поддерживаемая версия ОС Windows 10+.

Взвесив плюсы и минусы решений, мы остановились на WinAppDriver’e и FlaUI.

Пример работы с двумя выбранными решениями

Перед стартом написания тестов нужно выбрать инспектор UI-элементов. К примеру, здесь. Наши QA-специалисты предпочитают Inspect.exe и UISpy.exe.

WinAppDriver

Системные требования: Windows 10 (более новые версии ОС, к сожалению, не поддерживаются). Разумеется, необходимо скачать, инсталлировать и запустить WinAppDriver.exe. Затем мы поставили на машину Appium, запустили Appium Server (“демон”). Если не хочется писать на C# — напишем, например, на Python+Robot.

Создаём сессию приложения и подключаемся к ней:

1
2
3
4
5
6
7
8
9
10
class App:
 
   def __init__(self):
       desired_caps = {"app": "Microsoft.WindowsCalculator_8wekyb3d8bbwe!App"}
       self.__driver = webdriver.Remote(
           command_executor='http://127.0.0.1:4723',
           desired_capabilities=desired_caps)
 
   def setup(self):
       return self.__driver

Опишем шаг запуска приложения:

1
2
3
4
5
class CalculatorKeywordsLibrary(unittest.TestCase):
   @keyword("Open App")
   def open_app(self):
       self.driver = App().setup()
       return self.driver

Инспектором находим кнопки и кликаем по ним:

1
2
3
@keyword("Click Calculator Button")
def click_calculator_button(self, str):
   self.driver.find_element_by_name(str).click()

Описываем шаг получения результата:

1
2
3
4
5
6
7
@keyword("Get Result")
def getresult(self):
   display_text = self.driver.find_element_by_accessibility_id("CalculatorResults").text
   display_text = display_text.strip("Display is ")
   display_text = display_text.rstrip(' ')
   display_text = display_text.lstrip(' ')
   return display_text

Шаг выхода из приложения:

1
2
3
@keyword("Quit App")
def quit_app(self):
self.driver.quit()

В итоге, Robot-тест проверки вычисления квадратного корня будет выглядеть вот так:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Test Square
[Tags] Calculator test
[Documentation] *Purpose: test Square*
...
... *Actions*:
... — Check is the calculator started
... — Press button Four
... — Press button Square
...
... *Result*:
... — Result is 2
...
Assert Calculator Is Open
Click Calculator Button Four
Click Calculator Button Square root
${result} = Get Result
AssertEquals ${result} 2
[Teardown] Quit App

Запускать тест можно как обычный робот-тест из командной строки: robot test.robot. Существует подробная документация по BDD Robot Framework. Возможно тестирование приложений из WinStore и классических приложений.

Поддерживаемые типы локаторов:

  • FindElementByAccessibilityId

  • FindElementByClassName

  • FindElementById

  • FindElementByName

  • FindElementByTagName

  • FindElementByXPath

Можно сделать вывод, что это полностью Selenium-like тест. Можно применять любые паттерны тестирования: Page Object и т.д., добавить BDD framework (для Python, например, это Robot Framework или Behave).

Для дальнейшего изучения: подробная документация с примерами тестов на разных языках.  

FlaUI

Фактически является “обёрткой” над UI Automation libraries. Коммерческие утилиты, разобранные раньше, также являются “врапперами” над предоставленным Microsoft API для автоматизации.

Windows 7 PC, VS. Запускаем приложение и аттачимся к процессу:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Test]
        public void NotepadAttachByNameTest()
        {
            using (var app = Application.Launch("notepad.exe"))
            {
                using (var automation = new UIA3Automation())
                {
                    var window = app.GetMainWindow(automation);
                    Assert.That(window, Is.Not.Null);
                    Assert.That(window.Title, Is.Not.Null);
                }
                app.Close();
            }
        }

Инспектором находим поле ввода и отправляем в него строку:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Test]
public void SendKeys()
{
using (var app = Application.Launch("notepad.exe"))
{
using (var automation = new UIA3Automation())
{
var mainWindow = app.GetMainWindow(automation);
var textArea = mainWindow.FindFirstDescendant("_text");
textArea.Click();
//some string
Keyboard.Type("Test string");
//some key:
Keyboard.Type(VirtualKeyShort.KEY_Z);
Assert.That(mainWindow.FindFirstDescendant("_text").Patterns.Value.Pattern.Value, Is.EqualTo("Test stringz"));
}
app.Close();
}
}

Основные виды поиска элементов:

  • FindFirstChild

  • FindAllChildren

  • FindFirstDescendant

  • FindAllDescendants

Можно искать по:

  • AutomationId

  • Name

  • ClassName

  • HelpText

Можно реализовать поиск по любому поддерживаемому элементом паттерну, например,  по Value или LegacyAccessible. Или по условию.

1
2
public AutomationElement Element(string legacyIAccessibleValue) =>
            LoginWindow.FindFirstDescendant(new PropertyCondition(Automation.PropertyLibrary.LegacyIAccessible.Value, legacyIAccessibleValue));

Наша команда особенно оценила класс условных ожиданий  

Retry.While(foundMethod, Timeout, RetryInterval);

Внутри — выполнение в цикле входящего метода через заданный интервал на протяжении заданного таймаута. Больше никаких слипов основного потока исполнения.

Пример:

1
2
3
4
5
6
7
8
private static LoginWindow LoginWindow
{
get
{
Retry.WhileException(() => MainWindow.LoginWindow.IsEnabled);
return new LoginWindow(MainWindow.LoginWindow);
}
}

Создаем объект LoginWindow, только когда логин окно действительно отображается (интервал и таймаут — дефолтные). Такой подход избавляет от нестабильных тестов.

Для дальнейшего изучения: подробная документация на Github.

Сроки разработки тестов. Поддержка, стабильность UI-тестов

На шесть довольно объемных Regress-сценариев из примера было заложено три месяца разработки с “нуля”, включая ознакомление проектом, исследование доступных, описанных выше, фреймворков, создание скелета проекта АТ, настройка CI (continuous integration), менеджмент и коммуникации, сопроводительную документацию. Проект выполнен и сдан в срок.

При продолжении покрытия тестовых сценариев автотестами подготовительные операции, разумеется, будут занимать меньше времени, так как были реализованы на стадии пилота.

Помещаем тесты в Continuous Integration

Оба фреймворка поддерживают запуск тестов с использованием систем непрерывной интеграции. В нашей команде использовали TC и TFS.

При использовании фреймворка FLAUI, фреймворка SpecFlow и тестов, написанных на языке C#, в создании сборки нет ничего особенного (svc — build — run), кроме соблюдения некоторых условий на агенте исполнения тестов:

  • Агент сборки запускается как утилита из командной строки (вместо сервиса), обе системы это поддерживают. Необходимо установить автозапуск такого агента.

  • Automatic logon setup (Use SysInternals Autologon for Windows as it encrypts your password in the registry).

  • Отключить screensaver.

  • Отключить Windows Error Reporting. Справка на Gist: DisableWER.reg

  • Необходимо иметь на машине, где производится сборка и прогон тестов, активную десктопную сессию. Достаточно использовать для этого стандартное Windows-приложение.

  • RDC. Но часто можно встретить и совет пользоваться VNC (с аргументацией что: при подключении через Удаленный рабочий стол и последующем отключении, десктоп будет заблокирован  When you connect using Remote desktop, then disconnect, the desktop will be locked, and UI Automation will fail)

BDD-фреймворк Specflow имеет интеграцию “на лету” c TC и TFS. Т.е. непосредственно в прогоне тестов отображается отчет об успешных и проваленных тестах.

Пример ROI автотестов

Перед внедрением автоматизации подсчитать ROI сложно, поскольку существует огромное количество неизвестных факторов и коэффициентов. (И лучше не верить  калькуляции ROI в разделе прайсинга Test Complete).

Но после реализации пилотного проекта автоматизации можно привести некоторые цифры. Возьмем самую простую формулу ROI:

ROI = (Gain of Investment — Cost of Investment) / Cost of Investment

Стоимость проекта автоматизации за первый год (без поддержки):

3 месяца на покрытие автотестом Regress-прогона при работе одного инженера-разработчика в  тестировании: получается, 500 часов * Dev-ставка в час. Допустим, стоимость решения (Cost of investment) оплачивается заказчиком полностью в первый год (не делится по частям, и на покупку решения не берется кредит).

Выгода:

В первой статье мы подсчитали, что чистый “прогон” регресс-тестов вручную занимает 1 месяц: 2 недели первичный прогон + 2 недели вторичный прогон (без проверки новых тестов и сопутствующих расходов).

После разработки АТ-регресса (3 месяца), 9 месяцев в году прогоны регресс-теста руками не исполняются. Будем считать, что высвободившиеся ресурсы подключили к другим  проектам в компании. Сохранили: 1500 часов * QAставка в час * 2 человека в команде.

ROI = (1500*QA*2 — 500*Dev) / 500 * Dev = (6*QA — 1*Dev) / Dev

При взятии по рынку средних значений QA ставка = n, Dev ставка = 1,5n получаем:

ROI = (6n — 1,5n) / 1,5n = 3.

Первый год, очевидно, всегда отличается меньшей окупаемостью, показатели последующих лет будут значительно отличаться из-за отсутствия Cost.

Разумеется, это самый общий подсчет, не учитывающий поддержку, амортизацию, доработку отчетности, а также качество самих автотестов. Второй подсчет ROI рекомендуется проводить после первого года использования АТ с учетом этих дополнительных фактов.

Результат

Разработанные автотесты заменяют ручные силы команды QA и высвобождают команду из двух человек для более важных проектных задач. При этом оптимально расходуются ресурсы проекта.

Да, мануальное тестирование — необходимая часть разработки. Но если ПО состоит из десятков тысяч строк кода и требует двух-трех недель от разработки новой функции до релиза, автоматизация очень важна. Чтобы понять, выгодно ли покрытие всех работ автотестами и возможно ли оно, наша команда применяет стратегию Do Pilot: то есть,  автоматизирует участок работ при помощи выбранного фреймворка.

Тем не менее, если использовать в платных “коробочных” решениях для АТ все нужные функции и масштабировать команду хотя бы до двух инженеров — поддержка таких решений удорожает проект. Чтобы на заказчика ПО не ложилась необходимость платить в начале за само решение, а потом — каждый год — за его поддержку, мы рассмотрели несколько фреймворков для АТ с открытым кодом. Из предложений выбрали те, которые нас устраивают. Два найденных решения использовали для работы.

Автоматизация тестирования, хотя и требует подготовки по поиску фреймворка и разработке самих автотестов, оказывается значительно выгоднее ручных “прогонов”.

Обсудить в форуме