Про Selenium и один «велосипед». Продолжение. part 2

в 9:37, , рубрики: , bdd, java, jbehave, page object, selenium, thucydides, велосипединг, тестирование, метки: , , , , , ,

Вводную можно прочитать здесь.

5. Эксперимент.

image
Сам демо-проект со всей структурой был создан по инструкции из этой статьи (способ для Eclipse, Jbehave шаблон).

— Что должно было получиться.

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

Все это должно быть:
— описано в виде BDD – сценариев;
— с одновременным использованием возможностей моего самодельного фреймворка и thucydides;
— должен быть использован репортинг thucydides.

Получилось следующее.

— Модель взаимодействия с приложением.

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

для объектов, возникающих в отдельном окне браузера
image

вариация примера выше — для объектов, у которых есть ссылки на связанные с ними списки
image

главная страница вэб – клиента 1С
image

Есть еще несколько других примеров. Но того, что описано выше – более чем достаточно. Обратите внимание на подчеркнутые ссылки. Все объекты, с которыми следует работать, ссылаются на одно и тоже, их функции очень похожи.

Поэтому в моем примере все использование класса PageObject сводится к следующему:
минимальное описание функциональности всех объектов, с которыми можно работать в рамках вэб-клиента продукта 1С (работа с панелями кнопок, списком ссылок);
привязка частей, на которые эта страница будет «раскладываться», к определенному URL и предоставление полезных функций объекта PageObject. Их получают в свое распоряжение элементы декомпозиции страницы (наследники FunctionalPart).

image
OneCFunctionalContainer как раз и нужен для того, чтобы описывать ту функциональность, которую предстоит «протестировать». Перед каждым выполняемым действием будет проверено – а на той ли странице мы находимся (а в друг после наших действий «одинСка» нас перекинет в какой-нибудь хелп или на сайт с порнушкой). Это модифицированный алгоритм переключения вкладок/фрэймов. Кроме того, теперь «контейнер» может воспользоваться полезными механизмами работы (заложенными разработчиками thucydides) с элементами страниц. Примеры 1 и 2.

image
Как думайте, много отличий того, что в приведенном окне от того, что ниже?
image

Или вот такие примеры:
1 и 2

Firebug мне сказал, что разница только в идентификаторах и наборе (кстати, однородных) кнопок.
Таким образом, всю тестируемую функциональность я описал в наследниках класса FunctionalPart и один раз. А для тестов разница будет в том, как получить тот или иной набор элементов – с главной страницы или из вновь появившегося окна браузера:

page = (T) oneCInstance.getContentPage(contentClass, windowIndex);
page.getContent(Contractor.class).setCity(city)

или так

mainPage.getByCaptionFromMainPage(Contractor.class, caption);

Последняя составляющая модели.
Класс Pages нужен для создания экземпляров PageObject. Entity в чем-то аналогичен. Я его наделил свойствами класса Pages, спрятав внутрь нужный экземпляр, и создается этот экземпляр в момент создания экземпляра Entity (OneCApplication).

Я думаю, что можно было бы поступить и наоборот. Правда, в этом случае тестируемое приложение (если не пытаться копнуть немного вглубь) создавалось бы согласно правилам, заложенным в thucydides. Я же просто решил посвоевольничать и сократить потраченное время. Однако, альтернативное и верное направление будет представлено далее.

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

Но тут возникает вопрос. А как это можно использовать для заявленной модели описания тестов?

— Тесты

image
ScenarioSteps изначально нет в JBehave. Это изобретение разработчиков thucydides. Я бы сказал, что это очень полезное изобретение, т.к. для более широкого повторного использования того, что вызывает то или иное проверяемое действие, нужно было бы писать класс, скрывающий в себе Page Object'ы и манипулирующий ими.

Так предлагают нам работать авторы.

Мой же вариант несколько более хардкорный, т.к. я сильно торопился. Принципиальная разница в том, что я создаю webdriver снаружи. В описанном разработчиками варианте он создается средствами thucydides (как бы изнутри). Мне было интересно заставить этот механизм работать иначе – открывать браузер по моим настройкам, например. О многом я не знал на момент создания этого примера, поэтому, как минимум, его нельзя считать оптимальным. Но можно ознакомиться. А мысль о том, как же выполнять те же действия без всяких костылей будет описана далее.

Это действия, характерные для всех тестов – вход под учетной записью, выбор задачи, инициализация основных объектов на главной странице, на новых окнах и т.п.

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

Поясню. Если мы выполнили какое-то действие и проверили, что открылось что-то новое, то логично, что следующий шаг будет проведен уже над новой сущностью. Эту новую сущность можно запомнить и «промаркировать», чтобы тестировщик не запутался описывая сценарий. То же самое касается объектов, рисующихся на главной странице. Причем естественным «маркером» может служить видимый заголовок.

Если нужна конкретика, то можно создать наследника, имеющего в своем арсенале те же действия, «базовые состояния» + что — то, что нацелено на конкретные типы объектов. Таким я сделал набор действий с открытым элементом из списка контрагентов. У класса ScenarioSteps есть такой метод, который у меня не работает и падает с ClassCastException. А нечто подобное очень нужно (ниже расскажу почему). Я его перекрыл так. И чтобы синхронизировать базовые состояния «предка» и «дитя» (активное «промаркированное» окно, активные списки на главной странице и т.д.) я использую такой механизм.

Далее вступает в силу логика, заложенная в Jbehave.

Так предлагают нам использовать шаги сценария разработчики. Мой вариант почти такой же! Разница в том, что я (как было сказано, работал не «по технологии») сам создаю «шаги сценария» и собираю их в коллекцию. У меня была задумка сделать тесты сложнее. Например, проверки одновременной работы с двух открытых браузеров (два разных пользователя) над одним и тем же объектом с целью посмотреть, например, как применяются блокировки и как это видит пользователь. Или как видится информация, вводимая одним пользователем, для других в реальном времени.

И логично, что для этих совместных операций будут выполняться одни и те же действия (логин, выбор задачи и т.п.) над каждым открытым приложением. И поэтому был предусмотрен набор методов, который позволяет выполнять шаги с указанием индекса открытого клиента (по сути – индекса инициализированных «шагов сценария»).

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

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

Однако, все это легко выглядит на простых примерах…

Мне интересны сложные примеры, для средних и больших тестовых планов, которых в моей обойме, к сожалению, пока нет. Это является только догадкой о том, как можно работать. Хотя, если бы я серьезнее отнесся, то описал бы как достоинства (я думаю, что их было бы много), так и целый вагон недостатков описанного решения. Я ожидаю шквал критики (и надеюсь конструктивной) со стороны более опытных товарищей и ссылок на примеры использования Jbehave или того же thucydides для более серьезных проектов и случаев.

Следует сказать пару слов о репортинге.

Thucydides умеет строить отчеты, детализированные по шагам с прикрепленными скриншотами, иллюстрирующими состояние в конце каждого шага. Хотя, он может фотографировать каждое выполняемое действие.

Надо сказать, что построение точно таких же отчетов при созданном снаружи объекте webdriver'а – задача нетривиальная. Все потому, что фрэймворк им не управляет (не перезапускает, не закрывает). Экземпляр webdriver'a (а точнее – некий proxy — объект) создается согласно настройкам системных переменных машины, и перед запуском тестов создается стандартный слушатель, который скрывает его в себе и делает с него фотографии.

Но мой инструмент точно так же умеет фотографировать, у него есть логирование, в котором к сообщению лога может быть прикреплен файл (любой, в том числе – красивое фото). Ниже модель решения.
image

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

События webdriver'a и окон происходят внутри каждого шага. Почему бы не совместить эти функциональности?

Здесь мой StepListener. Он делает все тоже самое, что и предок, только не фотографирует. Фотки он получает «снаружи» и преобразует в читаемый для thucydides вид. По окончании теста происходит синхронизация накопленных результатов и скриншотов. Этот шпион инициализируется по инструкции, которая описана в этой статье
.
В результате, можно просматривать такое слайд-шоу:
image
1, 2 и 3.

— …и как правильно делать.

Эксперимент я считаю успешным – своих целей я добился. Однако проведен он был грубовато. Причина – я хотел настраивать проект снаружи, а не по стандартным правилам thucydides (которые мне кажутся неоправданно сложными). Я обещал описать правильный ход мыслей, в том числе описать набросок решения этой же задачи…

У меня есть абсолютно пустой класс, который, как оказалось, несет очень полезную функцию. Выяснить это удалось после последующего более детального прочтения инструкций Jbehave. Оказывается, если бы я наделил его логикой, то тогда бы он мог оказывать влияние на весь запуск тестов.

Если использовать этот файл в качестве внешней настройки параметров, тогда выполнение настройки могло бы выглядеть так (для примера хватит). Ниже показано, что будет открываться ожидаемый браузер (Chrome).
image

Если пройти по ссылке, что представлена далее, то можно увидеть альтернативный вариант создания объектов, описывающих взаимодействие с приложением. Ссылка. Все, что должно быть дальше, будет похоже на модель, описанную ранее. Описание тестов станет больше похожим на то, что предлагают разработчики thucydides. Хотя, это не избавляет от естественной необходимости подстраиваться под проверяемое поведение.

На этом все, ибо глава получилась большая! Кому интересно посмотреть результат, милости прошу на github.

6. Послесловие и возможные планы.

Надеюсь, что статья кому – то в чем-то помогла. Интересны мысли и комментарии публики. Я бы очень хотел, чтобы со мной кто-нибудь поделился своими лучшими практиками использования подходов behavior driven development и фрэймворка thucydides.

Что касается меня, мне было бы интересно копнуть глубже в Jbehave, а так же cucumber-jvm.

Что касается моего «велосипеда», то его дальнейшее будущее пока не ясно. Но хотелось бы:
— провести аналогичный эксперимент с использованием Selenide;
— проверить его возможности на мобильных приложениях с использованием Appium, Selendroid и ios-driver;
— испытать в настоящих, боевых условиях;
— переименовать проект на что-то более солидное, написать документацию и выложить в общедоступный maven – репозиторий. Пока вся сборка происходит локально.

А пока, всем спасибо за внимание. До встречи!

Автор: Sergey_Tikhomirov

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js