Автоматизация тестирования UI. От Coded UI к Cruciatus
Как вы знаете, 2ГИС помогает найти самую разную актуальную информацию об организациях города. Она собирается из различных источников при помощи специализированных продуктов, с которыми работают картографы 2ГИС, специалисты call-центра и отдела продаж. Эти продукты мы называем внутренними, и кроме сбора информации они также умеют её обрабатывать, фильтровать, объединять и выгружать в нужных форматах конечным приложениям 2ГИС.Внутренние продукты разрабатывают отдельные проектные команды, в основном, на стеке технологий Microsoft. Для отрисовки графического интерфейса используется WPF или наследственный WinForms. Одни приложения построены на элементах управления из «коробки», другие используют, например, библиотеку AvalonDock. Так же встречаются приложения, разработанные на платформе Catel.
Такое разнообразие порождает проблемы автоматизации тестирования. Мы их успешно решили в рамках проекта Cruciatus — собственного фреймворка, который позволяет упростить разработку тестов для проверки пользовательского интерфейса.
Несмотря на название, Cruciatus вполне легален и за его использование вас не упекут в Азкабан. В этой статье мы расскажем о Сruciatus подробнее.
Выбираем волшебную палочку инструмент Основной задачей автоматизации функционального тестирования является воспроизведение шагов тест-кейса. То есть, автотест должен повторять те же действия и проверки, что делает тестировщик при ручном тестировании. Эти задачи решаются с помощью специализированных инструментов, позволяющих эмулировать пользовательские действия.
Для desktop-приложений под Windows мы рассмотрели несколько самых популярных инструментов: Visual Studio CodedUI, Ranorex, White и выбрали наиболее подходящее для тестирования наших внутренних продуктов. Ранее на Хабре мы писали, какими принципами руководствовались при выборе.
Напомним, что мы сделали свой выбор в пользу CodedUI. Он не выигрывал по всем пунктам, но имел весомое преимущество в том, что работа с ним происходит непосредственно в Visual Studio, которая является основной средой разработки для разработчиков и тестировщиков.
Зачем нам бумеранг, если у нас есть грабли Рекордер является отличительной особенностью CodedUI, так как позволяет создавать тесты даже без навыков программирования.По нашему опыту сценарий CodedUI-теста легко воспроизводится для приложений типа «калькулятор». Однако, если интерфейс содержит множество нестандартных или динамических контролов, то возникают ошибки при их определении. Кроме того проблематично вносить изменения в код теста, так как сгенерированный рекордером код очень массивный и запутанный.
Так как к тому времени мы уже имели представление о работе CodedUI, мы отложили рекордер в сторону и стали писать код тестов самостоятельно, используя классы, предоставляемые пространством имён Microsoft.VisualStudio.TestTools.UITesting (их использует и сам CodedUI при генерации кода). Это позволило нам получать тесты с понятным, компактным кодом, но не избавило от проблем поиска элементов и их доступности. Что заблокировало дальнейшее продвижение автоматизации тестирования пользовательского интерфейса.
Представить себе CodedUI в работе можно как инфраструктуру, состоящую из классов фреймворка, тестируемого приложения и самих тестов. Подробнее компоненты изображены на схеме:
Нас полностью устраивала работа компоненты, эмулирующей действия мыши и клавиатуры: классы Mouse & Keyboard прекрасно с этим справляются. В отличии от классов, которые отвечают за доступ к приложению и являются крайними за упомянутую проблему поиска и доступности элементов. В связи с этим хочется их вырезать и заменить!
Своя обертка ближе к телу Для того, чтобы элемент приложения мог о себе что-то сказать, он должен реализовывать технологию Microsoft UI Automation. В таком случае он позволяет программно обращаться к нему, используя библиотеки из пространства имен System.Windows.Automation. Они применяются, например, в уже упомянутом на диаграмме классе WpfTestProvider. Мы попробовали напрямую использовать библиотеку Automation и получили отличный результат, избавившись от проблем поиска элемента и их доступности.Однако, предоставляемый функционал библиотеки Automation не даёт возможности выполнять обычные действия (найти элемент, кликнуть по нему, получить его текст и т.п.) за один метод. Поэтому пользоваться библиотекой Automation тестировщику в лоб было бы неправильно.
Так, следующим этапом развития нашего проекта стала разработка обёртки над UI Automation, которая заменит неудовлетворяющие нас классы,
аккумулирует удовлетворяющие,
а для тестировщика будет универсальным и удобным в использовании инструментом.
Магическое преображение Обёртка «выросла» и сейчас это инструмент для разработки функциональных тестов с кодовым названием Cruciatus. Приведем пример разработки тестового проекта с его использованием.Для работы необходимо построить карту элементов интерфейса. В ней указать тип и уникальный идентификатор каждого элемента, участвующего в тестировании. Важно, что тип выбирается из доступных в Cruciatus. Использование карты позволит легко поддерживать тесты при изменениях в интерфейсе, а изобразить её можно в виде дерева:
Используя карту, пишем тесты. Ниже пример теста, проверяющего, что при установленной галочке (у элемента SwitchCheckBox) элемент ComboBox включен, и наоборот:
[CodedUITest]
public class Class1
{
[TestMethod]
public void CheckingSwitchCheckBox ()
{
var app = new Application