Хабрахабр

Visual Studio Coded UI Tests: теория и практика применения в нашей компании

Picture 2

Автоматизированные тесты пользовательских интерфейсов — тема, к которой настороженно относятся даже опытные разработчики. При этом технология такого тестирования не представляет собой чего-либо экстраординарного, а в случае Visual Studio Coded UI Tests является расширением встроенной системы модульного тестирования Visual Studio Team Test. В этой статье я хочу остановиться как на теме UI-тестирования в общем, так и на нашем частном опыте применения Visual Studio Coded UI Tests в работе над статическим анализатором PVS-Studio.

Основы

Для начала давайте попробуем разобраться, почему же UI-тесты не так популярны среди разработчиков, как, например, классические Unit-тесты.

Все пирамиды похожи и содержат общую идею: как можно большее число тестов должно быть максимально приближено к коду. В сети существует множество так называемых «пирамид тестов», которые показывают оптимальное рекомендуемое распределение количества тестов по слоям приложения. Приведу пример одной из таких пирамид, содержащей дополнительные рекомендации по соотношению количества тестов в процентах. И наоборот.

Picture 4

У основания пирамиды находятся Unit-тесты. Действительно, такие тесты проще сделать ещё на этапе разработки, и они будут очень быстро выполняться. С другой стороны, на вершине пирамиды находятся автоматизированные тесты интерфейсов. Этих тестов не должно быть много, так как сложность их создания, а также время выполнения довольно велики. К тому же непонятно, кому доверить создание UI-тестов. Ведь по сути речь идет об эмуляции действий пользователя. Все это очень далеко от кода приложения, поэтому разработчики неохотно занимаются такой работой. А чтобы делать качественные автоматизированные тесты интерфейсов без участия (или с минимальным участием) программистов, требуется использование платных инструментальных средств. Совокупность всех этих факторов зачастую приводит к тому, что UI-тесты не делают вовсе, ограничиваясь однократным ручным тестированием новых функциональных возможностей. К тому же тесты интерфейсов крайне затратны не только на этапе разработки, но и в ходе дальнейшего жизненного цикла приложения. Даже незначительное изменение пользовательского интерфейса может привести к ошибкам выполнения множества тестов и необходимости их модификации.

Число автоматизированных тестов GUI (45) составляет примерно десятую часть от общего числа тестов PVS-Studio. Замечу, что в настоящее время наша система тестов в общем и целом соответствует рекомендациям. При этом число Unit-тестов у нас не так велико, но они дополнены массой других тестовых систем:

  • Тесты качества работы анализаторов (С/C++/C#/Java), в ходе выполнения которых производится проверка большого пула тестовых проектов на разных операционных системах (Windows, Linux, macOS) и сравнение логов новых предупреждений с эталонными;
  • Тесты специфических возможностей (отслеживание запуска компиляторов и т.п.);
  • Внешние тесты command-line приложений;
  • Тесты корректности сборки, установки и развёртывания;
  • Тесты документации.

На начальном этапе своего развития анализатор PVS-Studio представлял собой приложение для поиска ошибок при переносе C/C++ кода на 64-битную платформу. Да и назывался он в то время по-другому, «Viva64». С историей создания продукта можно ознакомиться в статье "Как 10 лет назад начинался проект PVS-Studio". После интеграции в Visual Studio 2005 анализатор обзавёлся графическим интерфейсом пользователя, по сути — интерфейсом самой IDE Visual Studio, в которой после установки плагина появлялось дополнительное меню для доступа к функциональности анализатора. Меню представляло собой два-три пункта, поэтому тестировать там было нечего. Да и Visual Studio на тот момент не содержал никакого встроенного инструментария для тестирования GUI.

Visual Studio Coded UI Tests и альтернативы

Всё изменилось с выходом Visual Studio 2010, в которой появилась интегрированная система создания UI-тестов: Visual Studio Coded UI Tests (CUIT). Базируясь на системе модульного тестирования Visual Studio Team Test, для доступа к визуальным элементам интерфейсов в CUIT изначально применялась технология MSAA (Microsoft Active Accessibility). В дальнейшем технология совершенствовалась и в настоящее время представляет собой развитую модель автоматизации пользовательского интерфейса для тестирования кода UIA (UI Automation). Она позволяет системе тестирования получать доступ к открытым полям (имя объекта, внутреннее имя класса объекта, текущее состояние объекта, его место в иерархической структуре интерфейса и т.п.) COM и .NET UI-элементов, а система позволяет эмулировать воздействия на данные элементы посредством стандартных устройств ввода (мышь, клавиатура). Сразу «из коробки» поддерживаются режимы записи действий пользователя при взаимодействии с интерфейсом (по аналогии с макросами Visual Studio), автоматизация построения «карты интерфейса» (свойства элементов управления, параметры их поиска и доступа к ним) вкупе с автоматической генерацией управляющего кода. В дальнейшем всю накопленную информацию несложно видоизменять и поддерживать в актуальном состоянии, а также настраивать тестовые последовательности по своему желанию, обладая при этом минимальными навыками программирования.

Ну а если нет желания или возможности использовать проприетарные тестовые среды, существует масса бесплатных продуктов и фреймворков. Более того, как я уже говорил ранее, сейчас при создании сложных интеллектуальных UI-тестов можно вообще обойтись без каких-либо навыков программирования, при условии использования специализированного платного инструментария. С её помощью легко создавать произвольные тестовые последовательности на языках программирования C# или VB. Система Visual Studio Coded UI Tests является промежуточным решением, позволяющим не только максимально автоматизировать процесс создания UI-тестов.

Используемый фреймворк несложен для понимания и в общем виде может быть представлен в виде диаграммы. Всё это позволяет значительно снизить затраты на создание и поддержку актуальности тестов GUI.

Picture 1

Из ключевых элементов следует отметить так называемые «адаптеры интерфейсов», находящиеся на самом нижнем уровне абстракции. Данный слой взаимодействует с конечными элементами интерфейса пользователя, а его возможности могут быть расширены при помощи дополнительных адаптеров. Выше следует слой, скрывающий технологии доступа к GUI от остальной части кода, включающей программные интерфейсы доступа и собственно код приложения тестирования, включающий все необходимые элементы для автоматизации тестирования. Технология является расширяемой, каждый уровень может быть дополнен необходимыми элементами в рамках возможностей фреймворка.

К основным возможностям CUIT от Microsoft можно отнести:

  • Функциональное тестирование интерфейсов пользователя. Поддерживаются классические Windows-based приложения, web-приложения и сервисы, WPF
  • Генерация кода (включая автоматическую) на языках VB/C#
  • Возможность интеграции в сборочный процесс
  • Локальные или удаленные запуски, сбор отчётности
  • Наличие средств записи и воспроизведения тестовых последовательностей
  • Хорошая расширяемость

Несмотря на ряд сложностей, связанных с CUIT, использование данной технологии тестирования является предпочтительным ещё по ряду причин:

  • Эффективное взаимодействие разработчиков и тестировщиков в рамках одного инструментального средства и языка программирования
  • Дополнительные возможности работы с «картой интерфейса», позволяющие производить идентификацию элементов управления «на лету», синхронизировать элементы и осуществлять дозапись тестовых последовательностей
  • Тонкая настройка механизма воспроизведения, позволяющая наряду с базовыми настройками, такими как задержка между операциями, таймаут поиска элемента и т.п., использовать в коде специализированные механизмы. Например, блокировку текущего потока до момента активизации (визуализации) элемента управления при помощи методов WaitForControlExist или WaitForReady с перечислением WaitForReadyLevel и т.п.
  • Возможность программирования неограниченно сложных тестов

Не буду далее вдаваться в теоретические аспекты технологии Visual Studio Coded UI Tests, все они подробно изложены в соответствующей документации. Там же вы сможете найти развернутые пошаговые инструкции по созданию простейшего UI-теста на базе этой системы. И да, система не бесплатна, для работы с ней потребуется Visual Studio Enterprise.

Существует множество других решений. Описанная технология не является единственной представленной на рынке. При этом выбор конкретной системы не всегда будет зависеть от её цены. Все альтернативные системы UI-тестирования можно разделить на платные и бесплатные. Также важна поддержка необходимой тестовой среды — операционных систем и приложений. Например, немаловажным фактором может служить возможность создания тестов без необходимости программирования, но при этом тесты, возможно, не будут в достаточной степени гибкими. Приведу несколько популярных систем и технологий для тестирования GUI. Наконец, на выбор могут оказать влияние чисто специфические особенности приложения и его интерфейса.

Платные: TestComplete (SmartBear), Unified Functional Testing (Micro Focus), Squish (froglogic), Automated Testing Tools (Ranorex), Eggplant Functional (eggplant) и др.

White + UIAutomationVerify, . Бесплатные: AutoIt (windows), Selenium (web), Katalon Studio (web, mobile), Sahi (web), Robot Framework (web), LDTP (Linux Desktop Testing Project), Open source frameworks: TestStack. NET Windows automation library и др.

Тем не менее, очевидно, что бесплатные системы, как правило, ориентированы на какую-то конкретную операционную систему или технологию тестирования. Конечно, данный список не является полным. Общим правилом является то, что среди платных систем вы гораздо быстрее найдете что-то подходящее именно под ваши нужды, разработка и сопровождение тестов будет проще, а список поддерживаемых тестовых сред исчерпывающим.

В нашем случае проблема выбора не стояла: с выходом Visual Studio 2010 с дополнением Coded UI Tests стало возможным легко добавить в наше тестовое окружение набор функциональных тестов для проверки пользовательского интерфейса плагина PVS-Studio для Visual Studio.

UI-тесты PVS-Studio

Итак, тесты GUI в нашей компании применяются уже более 6 лет. Первоначальный набор UI-тестов для Visual Studio 2010 базировался на единственно доступной в тот момент технологии MSAA (Microsoft Active Accessibility). С выходом Visual Studio 2012 технология MSAA получила значительное развитие и в настоящее время носит название UIA (UI Automation). Было принято решение в дальнейшем использовать UIA, а тесты на базе MSAA оставить для тестирования работы плагина к Visual Studio 2010 (мы поддерживаем и тестируем плагины для всех версий Visual Studio, начиная с Visual Studio 2010).

При этом в тестовом проекте обе этих ветки использовали общую карту интерфейса и разделяемый код. В результате у нас образовалось две «ветки» UI-тестов. В коде это выглядело примерно так (метод для сброса настроек Visual Studio к стандартным перед запуском теста):

public void ResetVSSettings(TestingMode mode)
#endregion //UIA Mode ....
}

При внесении изменений в интерфейс плагина приходилось вносить правки в обе ветки UI-тестов, а добавление новой функциональности приводило к необходимости дублирования элемента интерфейса в карте: то есть создавать два разных элемента для каждой из технологий MSAA и UIA. Все это требовало много сил не только на создание или изменение тестов, но и на поддержание тестовой среды в стабильном состоянии. Остановлюсь на данном аспекте более подробно.

В основном это связано с сильной зависимостью такого тестирования от множества внешних факторов. По моим наблюдениям, стабильность тестовой среды при тестировании GUI является значительной проблемой. Здесь много чего может «пойти не так». Ведь по факту производится эмуляция действий пользователя: нажатие на клавиши, перемещение курсора мыши, клики мышью и т.п. Также, неожиданно разрешение монитора может оказаться недостаточным для отображения какого-либо элемента управления, и он не будет найден тестовой средой. Например, если в ходе выполнения теста кто-то будет взаимодействовать с клавиатурой, подключенной к тестовому серверу.

Ожидание:

Picture 3

Реальность:

Небрежно настроенный (и не найденный потом) элемент карты интерфейса — практически лидер проблемного поведения. Например, мастер построения карты интерфейса Visual Studio Coded UI Tests при создании нового элемента управления использует для него критерии поиска типа «Equals» по умолчанию. То есть требуется точное соответствие названий свойств заданным значениям. Обычно это работает, но иногда стабильность выполнения тестов можно значительно повысить, используя менее строгий критерий поиска «Contains» вместо «Equals». Это лишь один из примеров «тонкой настройки», с которой вы можете столкнуться при работе над UI-тестами.

В этом случае к проблеме поиска элемента добавятся вопросы настройки задержки воспроизведения до момента появления окна и последующей синхронизации работы. Наконец, некоторые ваши тесты могут заключаться в выполнении какого-либо действия и дальнейшем ожидании результата, который, например, связан с отображением окна. Некоторые из этих проблем удается решить стандартными методами фреймворка (WaitForControlExist и т.п.), а для иных придется изобретать хитроумные алгоритмы.

В этом тесте сначала открывается пустая среда Visual Studio, затем туда загружается некое тестовое решение, которое целиком проверяется при помощи PVS-Studio (меню «PVS-Studio» -> «Check» -> «Solution»). С подобной задачей мы столкнулись в ходе работы над одним из тестов нашего плагина. В зависимости от ряда условий, проверка может занимать не всегда одинаковое время, поэтому простые таймауты здесь не работают. Проблема состояла в определении момента, когда проверка будет завершена. В ходе проверки появляется окно со статусом работы, но это окно можно скрыть, и проверка будет продолжаться. Также нельзя воспользоваться штатными механизмами приостановки работы тестового потока и ожиданием появления (или скрытия) какого-либо элемента управления, так как не к чему привязаться. на это окно нельзя ориентироваться (к тому же у него есть настройка «Не закрывать после завершения анализа»). Т.е. Решение было найдено. А алгоритм хотелось сделать более общим для того, чтобы по возможности иcпользовать его для различных тестов, связанных с проверкой проектов и ожиданием завершения этого процесса. Нам оставалось через некий интервал времени проверять свойство «Enabled» этого пункта меню (через объект карты интерфейса) и в случае обнаружения, что элемент стал активным, считать процесс проверки решения завершённым. После запуска проверки и до момента её завершения тот самый пункт меню «PVS-Studio» -> «Check» -> «Solution» является неактивным.

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

За это время было создано несколько десятков тестовых последовательностей и написано много вспомогательного кода. Напомню, что система UI-тестов в нашей компании развивалась с 2010 года. К этому моменту старая ветка тестирования плагина для Visual Studio 2010 потеряла актуальность и была заброшена, но просто так вырезать этот «мёртвый» код из проекта было нельзя. К тестам плагина со временем добавились тесты приложения Standalone. А во-вторых, более половины элементов существующей карты интерфейса относились к старой технологии MSAA, но были повторно использованы (вместо дублирования) во многих новых тестах наравне с UIA-элементами (это возможно благодаря преемственности технологий). Во-первых, как я показывал ранее, код был достаточно глубоко интегрирован в тестовые методы. При этом к «старым» элементам была привязана масса как автоматически сгенерированного кода, так и содержимого тестовых методов.

В целом тесты работали нормально, но время от времени какой-нибудь тест «падал» по непонятным причинам. К осени 2017 года назрела необходимость улучшения системы UI-тестов. В каждом конкретном случае приходилось проходить по дереву карты интерфейса до конкретного элемента и проверять его критерии поиска и другие настройки. Точнее, причина обычно заключалась в поиске элемента управления. Учитывая разросшуюся к этому моменту (и во многом избыточную) карту интерфейса, а также наличие «мёртвого» кода, данный процесс требовал значительных усилий. Иногда помогал программный сброс этих настроек перед выполнением теста.

Некоторое время задача «ждала своего героя», пока, наконец, не попала ко мне.

Picture 5

Не буду утомлять вас описанием нюансов. Скажу только, что работа была несложной, но она потребовала значительной усидчивости и внимания. На всё про всё у меня ушло примерно две недели. Половину этого времени я потратил на рефакторинг кода и карты интерфейсов. В оставшееся время занимался стабилизацией выполнения тестов, которая в основном свелась к более тонкой настройке критериев поиска визуальных элементов (правка карты интерфейса), а также некоторой оптимизации кода.

Но самое главное, UI-тесты стали показывать более стабильную работу и требовать меньше внимания. В результате удалось примерно на 30% сократить объем кода тестовых методов, а число элементов управления в дереве карты интерфейсов уменьшилось вдвое. Собственно, для этих целей и нужна система UI-тестов. А падения стали чаще происходить по причинам внесения изменений в функциональность анализатора или при обнаружении несоответствий (ошибок).

Таким образом, в настоящее время система автоматических тестов интерфейса PVS-Studio имеет следующие базовые характеристики:

  • Visual Studio Coded UI Test
  • 45 сценариев
  • 4 095 строк кода тестовых методов
  • 19 889 строк auto-generated кода (без учета размера xml-файла хранения настроек UI Map)
  • 1 час 34 минуты выполнения (средняя величина по результатам последних 30 запусков)
  • Работа на выделенном сервере (запуск утилитой MSTest.exe)
  • Контроль работы и анализ отчета о выполнения (Jenkins)

Заключение

В заключение хочу привести список критериев успешности автоматических тестов GUI, который основан на анализе нашего опыта работы с этой технологией (некоторые из критериев применимы и для других технологий тестирования, например, Unit-тестов).

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

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

Там, где это возможно, обязательно используйте автоматические средства генерации кода и записи последовательностей. Минимизация ручного труда. Так вы значительно ускорите разработку и минимизируете вероятность ошибок (не всегда просто найти причину падения UI-теста, особенно если ошибка допущена в коде работы с фреймворком).

Чем проще будут ваши тесты, тем лучше. Простые и независимые интеллектуальные тесты. Также обеспечьте независимость тестов друг от друга. Старайтесь делать отдельный тест для проверки конкретного элемента управления или моделируемой ситуации. Падение одного из тестов не должно оказывать влияния на весь процесс.

Используйте префиксы в названиях однотипных тестов. Понятные имена. Также используйте группировку тестов по возможности. Многие среды позволяют запускать тесты с фильтрацией по имени.

Обеспечьте выполнение тестов на выделенном сервере с минимальными внешними воздействиями. Изолированная среда выполнения. Убедитесь, что во время тестового прогона не выполняются другие приложения, взаимодействующие, например, с рабочим столом и отображающие сообщения. Отключите все внешние устройства пользовательского ввода, обеспечьте необходимое разрешение экрана для вашего приложения или используйте аппаратную «заглушку», имитирующую подключение монитора с высоким разрешением. Также необходимо спланировать время запуска и учитывать максимальную продолжительность выполнения тестов.

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

Visual Studio Coded UI Tests: Theory and Our Company's User Experience Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Sergey Khrenov.

Показать больше

Похожие публикации

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

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

Кнопка «Наверх»