Блог

Полезные статьи и новости о жизни WaveAccess

Как автоматизировать тестирование на desktop. Часть 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.

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

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

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

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

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

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

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

@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

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

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

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

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. Запускаем приложение и аттачимся к процессу:

[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();
            }
        }

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

[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. Или по условию.

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

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

Retry.While(foundMethod, Timeout, RetryInterval);

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

Пример:

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: то есть,  автоматизирует участок работ при помощи выбранного фреймворка.

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

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

Если вам нужно произвести тестирование ваших приложений в оптимальные сроки и не увеличивая затраты без необходимости, мы с радостью ответим на ваши вопросы: 

Телефон: +7 812 407 2350

E-mail: hello@wave-access.com 

Заказать звонок

Удобное время:

Отменить

Пишите!

Присоединить
Файл не больше 30 Мб.
Отменить