Всем привет!
Эта статья является продолжением моей прошлой публикации Про Selenium и один «велосипед», в которой я попытался описать прототип некоего решения, которое мог бы использовать на текущем месте работы для тестирования клиентской части вэб — приложения. Родилось оно благодаря желанию углубленно разобраться с возможностями Selenium API.
Я думаю, что топик может быть интересным для новичков, что примеряют на себя методики из behavior driven development, пробуют работать с фрэймворком thucydides, и в большей степени тем, кто обычно имеет дело с Java-кодом.
А так же интересен взгляд на идеи дилетанта тех, кто уже съел здесь стаю собак. Я постараюсь вкратце описать некий эксперимент.
Итак, поехали!
План:
1. Флэшбэк.
2. В чем суть эксперимента?
3. Почему BDD?
4. Немного про thucydides.
5. Эксперимент.
— Что должно было получиться.
— Модель взаимодействия с приложением.
— Тесты
— … и как правильно делать.
6. Послесловие и планы.
1. Флэшбэк.
Если честно, в своем прошлом посте я рассчитывал на какую-то конструктивную критику или на какие-то ценные советы. В принципе, все это я получил, но не в том объеме, на который надеялся. Остапа тогда понесло… Постараюсь вести свое повествование сжато и доносить мысли в концентрированном виде, но с логическими выводами.
Вкратце еще раз пройдусь по содержанию предыдущей главы. Основные идеи заключаются том, чтобы:
— поддерживать множество реализаций WebDriver'а и для создания использовать единственный способ.
— облегчить доступ к реализациям других полезных интерфейсов, входящих в состав Selenium API;
— возможность поддерживать несколько открытых экземпляров WebDriver'а в одном выполняющемся тесте. Согласитесь, что может возникнуть ситуация, когда мы хотим проверить с точки зрения пользователя совместную работу с неким доступным компонентом (например, документом Google drive или Яндекс диск, находящемся в совместном доступе).
— упростить описание интерактивного взаимодействия с приложением, чьи страницы могут открываться в других окнах браузера или вкладках, а так же содержать фрэймы. Одно из решений — автоматизация переключений объекта Webdriver'а.
— и, на мой взгляд, самое главное – составлять описание тестируемого приложения с точки зрения составляющих его компонентов (страниц/окон/вкладок и т.д.), способов взаимодействия с ними. За пример было взято вот это.
Это дерево объектов. Вид из TestComplete. Возможно, пример не самый удачный. Т.е. дерево структурных компонентов, как простых, так и сложных. Сложные компоненты могут быть описаны в виде классов, которые можно наследовать. Объекты этих классов можно использовать, причем одновременно и в разных местах.
Среди существующих инструментов поверх Selenium Webdriver я бы выделил Yandex-qatools Htmlelements. Он реализует похожий принцип. Но, как мне показалось, он описывает физически объединенные между собой типизированные элементы, которые потом группируются в описания проверяемых вэб-страниц. Это предположение можно оспорить.
Я же, как мне кажется, пытаюсь выделить повторяющиеся элементы, которые может быть физически не связанны до некоторых пределов (не объединены каким-нибудь div'ом, например), но совместно присутствуют и выполняют общую функцию или набор функций. Эти наборы можно расширить за счет наследования, можно спрятать один внутри другого или передать наружу (например, в тест) для дальнейшей работы. Может получиться сложный Page Object.
Хочу, при острой необходимости, чтобы внутри такого контейнера можно было использовать другие инструменты, работающие с Webdriver и выполняющие те или иные функции лучше. В прошлый раз я вскользь описал пример совместного использования того, что получилось и уже упомянутого Htmlelements. Очень хочется провести такой эксперимент с Selenide.
Но, при всех описанных плюшках, я считаю, что процентов 60-70 всех тестов (не меньше) должны быть unit-тесты и тесты бэк-энда. А все остальное – тесты, которые могут сказать, что пользователь сможет работать с конечным продуктом.
— простые кастомизация и деплой;
— придумать красивые плюшки. Например, набор красивых интерфейсов и их «стандартных» реализаций, которые, к примеру, позволяют определенным образом обрабатывать некоторые исключительные ситуации, фиксировать события webdriver’а, открытого окна/вкладки и т.д. Ниже показан результат (пока еще грубоватый) работы одной такой реализации. Она перехватывает сообщения лога и превращает их в детализацию отчета TestNG.
Отчет. Скриншот.
С момента публикации удалось:
— добавить поддержку PhantomJS;
— немного улучшить формирование детализации отчета TestNG. Впоследствии, я вынес эти инструменты в отдельный артефакт;
— оптимизировать исходный код, убрать лишние детали.
— окончательно сформировать модель описания приложения. Ее составляющие:
IDecomposable.java;
FunctionalPart.java – это то, что в предыдущей статье называлось Page;
Entity.java – представление открытого клиента в целом.
Наглядно вся модель представлена ниже.
— удобная и гибкая настройка предполагаемого проекта. Пример в формате JSON. Можно сделать одну обобщенную конфигурацию и можно сделать несколько других, которые ее частично перекроют и будут использованы для уточнения или в виде параметров для создания самых разных объектов.
— многое другое, но все это не поместится в формат одной статьи. Если в этом есть смысл, то опишу позже.
2. В чем суть эксперимента?
С недавних пор у меня появился интерес к behavior driven development как к некой концепции, а так же к инструментам, которые используются для описания проводимых тестов в подобном ключе. Стало интересно, сможет ли мой продукт быть использован как один из элементов стека такого автотестирования?
Кроме того, мне было интересно, смогут ли два инструмента, которые построены на использовании дизайн-паттерна Page Object ужиться, органично дополняя друг — друга имеющимися полезными возможностями? Идея может и бредовая, но думаю, может быть интересна как исследовательская задача. И, в качестве результата, поделиться с публикой своими соображениями.
Поэтому, эксперимент был проведен с использованием фрэймворка thucydides, т.к. это наиболее известный инструмент, в котором все выше названное максимально представлено. Для этого я использовал версии 0.9.227 — 229 thucydides-core.
В качестве подопытного кролика, в силу некоторых особенностей, был выбран вэб-клиент 1С.
P.S. Хочу извиниться перед фирмой 1С, если замусорил список контрагентов, и это принесло неудобства. Но, думаю, это послужило благим целям.
3. Почему BDD?
У меня нет цели описать этот подход со всеми его преимуществами и недостатками. Для этого я посоветую прочитать это и это, и еще много других источников.
Я лучше расскажу, почему такой подход может показаться интересным кому-то и показался интересным мне с точки зрения его использования в автоматизированном тестировании:
— отделение логики теста от кода, который что-то проверяет или выполняет то или иное действие;
— возможность описывать автоматизированные тесты простым человеческим языком, хоть и не в свободной форме;
— вся нагрузка при автоматизации приемочного тестирования теперь смещается в сторону разработки и поддержки отдельных тестовых процедур (методов каких-либо классов), а не автоматизированного теста целиком;
— ну и, как подсказывает кэп, повторное использование описанных тестовых процедур;
— универсальность. Мне кажется, такой подход можно использовать как в приемочном тестировании, так для выполнения unit-тестов.
Предположим, что у меня есть сценарий, описанный и хранящийся в TestLink, например:
1. Do something | |
2. Do another action | |
3. Do one more action. | Something is expected. |
Ok! Тест можно описать так:
@Test
public void someTest()
{
//Step 1. Do something
//much code
//Step 2. Do another action
//much code
//Step 3. Do one more action.
//much code
//Checking the result
//Some assert
//ect.
}
Чуть лучше смотрится это:
public void doSomething(Object... params)
{
//much code
}
public void doAnotherAction(Object... params)
{
//much code
}
public void doOneMoreAction(Object... params)
{
//much code
}
public void checkOutResult(Object... params)
{
//Some assert
}
@Test
public void someTest()
{
//Step 1. Do something
doSomething();
//Step 2. Do another action
doAnotherAction();
//Step 3. Do one more action.
doOneMoreAction();
//Checking the result
checkOutResult();
//ect.
}
Должен признаться, что в силу некорых технических ограничений, выше описанные реализации приходится постоянно наблюдать, да и самому описывать автотесты в подобном ключе. Чем мне такой подход не нравится, так это тем, что в случае изменения логики проверки придется переделывать весь тест (метод/группу методов/целый класс) и скорее всего, не один.
Упрощает ситуацию выделение отдельных действий в методы. Но даже тут придется импортировать классы, в которых эти методы содержатся, создавать объекты этих классов и т.д., и при изменении теста менять одни методы на другие. В общем, об этом я написал чуть выше.
Попробуем описать этот тест с использованием, например, фрэймворка Jbehave.
У меня получился класс с такими методами:
@Given("Do something")
public void doSomething(Object... params)
{
//much code
}
@Given("Do another action")
public void doAnotherAction(Object... params)
{
//much code
}
@When("When do one more action.")
@Given("One more action is done")
public void doOneMoreAction(Object... params)
{
//much code
}
@Then("Something is expected")
public void checkOutResult(Object... params)
{
//Some assert
}
То, что описано в левой части пунктов 1 и 2 моего сценария, является предусловием (Given), при выполнении которого можно переходить к 3. В левой части 3 описано действие, которое нужно проверить (When), хотя при других обстоятельствах оно может оказаться предусловием (Given). И в правой части сама проверка (Then). Стоп, а где сам тест? Он ниже, написанный в блокноте, имеющий расширение *.story:
Scenario: Some test
Given Do something
And Do another action
When Do one more action.
Then Something is expected
Дальнейшие наши шаги, я думаю очевидны. Мы сможем составить небольшой тестовый план используя только эти реализованные шаги и описания пускай на формализованном, но человеческом языке.
Я не хочу проводить большую и скучную лекцию о возможностях описания тестов в BDD-кличе на Jbehave, ну хотя бы потому, что я сам пока недостаточно владею инструментом – не хватило времени на его глубокое изучение и использование.
Помимо всего прочего мне интересны возможности интеграции инструментов, которые используются для описания тестов в BDD – стиле с тест-менеджмент системами. Получается, что если нужные шаги описаны программным кодом, каждый добавленный тест будет подхватываться CI системой и присутствовать в автоматизированном плане, при определенных условиях. Ведь должна же быть какая-то готовая библиотека? Я не думаю, что задача новаторская и никто ее не решал. Пока встречаю разрозненные описания, подобные этому.
4. Немного про thucydides.
Назван инструмент в честь древнегреческого историка и полководца, чьи красочные описания Пелопонесской войны дошли до наших дней.
Надо сказать, что его так назвали не зря, т.к.:
— Интеграция «из коробки» с Jbehave;
— Набор дополнительных хелперов, например шаги;
— Интеграция с баг-трэкерами;
— Возможности прослушивать выполняемые шаги с помощью реализаций интерфейса StepListener.
— Ну и, конечно, красивые отчеты, которые есть «в коробке», и которые, глядя на исходники, можно делать самим. Пример 1, пример 2 и пример 3;
— А так же набор вспомогательных инструментов для работы со страницами вэб -приложений и их элементами. Их можно посмотреть, например, здесь и здесь
Однако:
— он просто огромен. Не уверен, что существует много проектов (имею право на догадки), где используется хотя бы 50% того, что в него вложено. Производит впечатление обвертки вокруг всего, чего только можно;
— я считаю, что усложненный деплой, т.к. многие настройки и параметры, если без каких-либо дополнительных усилий, нужно указывать в системных свойствах. Хотелось бы, чтобы эти настройки переносились вместе с локальным чек аутом проекта из репозитория;
— из разговоров с некоторыми товарищами сложилось впечатление, что реализация чего-то нетривиального может заставить серьезно задуматься. Средства есть, но они неочевидны. Пример.
Но многие пользуются этим инструментом, он себя зарекомендовал. А чего бы самому не попробовать?!
Кому интересно продолжение, смотреть здесь.
Автор: Sergey_Tikhomirov