Serenity BDD (ранее известный как Thucydides ) — это библиотека отчетов с открытым исходным кодом, которая помогает вам писать более структурированные, более удобные в обслуживании критерии автоматического принятия, а также создает содержательные содержательные отчеты о тестах (или «живую документацию»), которые не только сообщают о результатах тестов, но и какие функции были проверены. В этой статье мы продолжим наше исследование Serenity и посмотрим, как он работает с популярным инструментом BDD Cucumber-JVM .
В предыдущей статье мы рассмотрели, как можно использовать Serenity BDD с JUnit для написания чистых, читаемых автоматических приемочных тестов, и как Serenity также помогает вам создавать автоматизированные веб-тесты на основе WebDriver, которые легче понять и поддерживать. В этой статье мы будем использовать тот же пример домена, что и в предыдущей, но мы снова пройдемся по основам, поэтому вы можете сразу перейти к этой статье, даже если вы еще не читали предыдущую.
1. Основы BDD
Поведенческая разработка, которая является основной концепцией, лежащей в основе многих функций Serenity. Команда, использующая Behavior Driven Development, использует беседы и совместную работу на конкретных примерах для выработки общего понимания функций, которые они должны создавать. Беседы о конкретных примерах и контрпримеры — отличный способ избавиться от любых скрытых предположений или недопонимания относительно того, что должна делать функция.
Предположим, вы создаете сайт, где художники и ремесленники могут продавать свои товары онлайн. Одной из важных функций для такого сайта будет функция поиска. Вы можете выразить эту функцию, используя формат карты истории, обычно используемый в гибких проектах, таких как:
In order to find items that I would like to purchase As a potential buyer I want to be able to search for items containing certain words
Чтобы сформировать общее понимание этого требования, вы можете обсудить несколько конкретных примеров. Разговор может идти примерно так:
- «Итак, приведите пример того, как поиск может работать».
- «Ну, если я ищу шерсть , то я должен видеть только шерстяные изделия».
- «Звук достаточно прост. Существуют ли другие варианты функции поиска, которые могли бы привести к другим результатам?»
- «Ну, я мог бы также фильтровать результаты поиска; например, я мог искать только шерстяные изделия ручной работы».
- «Таким образом, вы можете фильтровать по предметам ручной работы. Не могли бы вы привести примеры других типов товаров, по которым вы хотели бы фильтровать?»
И так далее. На практике многие из обсуждаемых примеров становятся «критериями приемлемости» для функций. И многие из этих критериев приемки становятся автоматическими приемочными испытаниями. Автоматизация тестов приемлемости обеспечивает ценную обратную связь для всей команды, так как эти тесты, в отличие от тестов модульных и интеграционных тестов, обычно выражаются в бизнес-терминах и могут быть легко понятны не разработчиками. И, как мы увидим далее в этой статье, отчеты, которые создаются при выполнении этих тестов, дают четкое представление о состоянии приложения.
2. Написание критериев приемки с помощью Cucumber-JVM
Cucumber — популярный инструмент автоматизации тестирования BDD. Cucumber-JVM — это Java-реализация Cucumber, на которой мы сосредоточимся в этой статье. В Cucumber вы выражаете критерии принятия в естественной, удобочитаемой форме. Например, мы могли бы написать пример «шерстяной шарф», упомянутый выше:
Given I want to buy a wool scarf When I search for items containing 'wool' Then I should only see items related to 'wool'
Этот формат известен как Gherkin и широко используется в Cucumber и других основанных на Cucumber инструментах BDD, таких как SpecFlow (для .NET) и Behave (для Python). Gherkin — это гибкий, легко читаемый формат, который может быть написан совместно с владельцами продуктов, чтобы гарантировать каждому. Слабо структурированный формат « Дается когда» помогает людям сосредоточиться на том, чего они пытаются достичь, и на том, как они узнают, когда получат это.
Иногда таблицы могут использоваться для суммирования нескольких разных примеров одного и того же сценария. В Gherkin вы можете использовать примеры таблиц, чтобы сделать это. Например, следующий сценарий иллюстрирует, как вы можете искать различные типы изделий из разных материалов:
Scenario Outline: Filter by different item types Given I have searched for items containing '<material>' When I filter results by type '<type>' Then I should only see items containing '<material>' of type '<type>' Examples: | material | type | | silk | Handmade | | bronze | Vintage | | wool | Craft Supplies |
В этой статье мы узнаем, как автоматизировать эти сценарии, используя Cucumber и Serenity BDD. Не беспокойтесь, если вы раньше не использовали Cucumber, поскольку мы рассмотрим достаточно примеров, чтобы вы могли увидеть, как он работает, даже если вы новичок в инструментах автоматизации тестирования BDD.
3. Написание исполняемых спецификаций с Cucumber и Serenity
3.1. Написание сценария
Давайте начнем с первого примера, описанного выше. В Cucumber сценарии хранятся в файлах объектов, которые содержат общее описание функции, а также ряд сценариев. Файл функций для приведенного выше примера вызывается search_by_keyword.feature
и выглядит примерно так:
Feature: Searching by keyword In order to find items that I would like to purchase As a potential buyer I want to be able to search for items containing certain words Scenario: Should list items related to a specified keyword Given I want to buy a wool scarf When I search for items containing 'wool' Then I should only see items related to 'wool'
Эти файлы функций могут быть размещены в разных местах, но вы можете уменьшить объем конфигурации, который вам нужно сделать с Serenity, если вы поместите их в src/test/resources/features
каталог.
Вы обычно организуете файлы объектов в подкаталогах, которые отражают требования более высокого уровня. Например, в следующей структуре каталогов у нас есть определения функций для нескольких функций более высокого уровня: search и shopping_cart :
|----src | |----test | | |----resources | | | |----features | | | | |----search | | | | | |----search_by_keyword.feature | | | | |----shopping_cart | | | | | |----adding_items_to_the_shopping_cart.feature
3.2. Сценарий Бегун
Cucumber запускает файлы объектов через JUnit и нуждается в специальном классе для запуска тестов, чтобы фактически запускать файлы объектов. Когда вы запускаете тесты в Serenity, вы используете CucumberWithSerenity
тестовый прогон . Если файлы компонентов находятся не в том же пакете, что и класс тестового бегуна, вам также необходимо использовать этот @CucumberOptions
класс для предоставления корневого каталога, в котором можно найти файлы компонентов . Тестовый прогон для запуска всех файлов объектов выглядит следующим образом:
package net.serenity_bdd.samples.etsy.features; import cucumber.api.CucumberOptions; import net.serenitybdd.cucumber.CucumberWithSerenity; import org.junit.runner.RunWith; @RunWith(CucumberWithSerenity.class) @CucumberOptions(features="src/test/resources/features") public class AcceptanceTests {}
3.3. Определения шагов
В Cucumber каждая строка сценария Gherkin отображается на метод в классе Java, известный как определение шага . Это использование аннотаций нравятся @Given
, @When
и @Then
матч линия в сценарии к методам Java. Вы определяете простые регулярные выражения для указания параметров, которые будут переданы в методы:
public class SearchByKeywordStepDefinitions { @Steps BuyerSteps buyer; @Given("I want to buy (.*)") public void buyerWantsToBuy(String article) { buyer.opens_etsy_home_page(); } @When("I search for items containing '(.*)'") public void searchByKeyword(String keyword) { buyer.searches_for_items_containing(keyword); } @Then("I should only see items related to '(.*)'") public void resultsForACategoryAndKeywordInARegion(String keyword) { buyer.should_see_items_related_to(keyword); } }
Эти определения шагов используют Serenity для организации кода определения шагов в более повторно используемые компоненты. @Steps
Аннотацию говорит Serenity , что эта переменная является библиотека Шаг. В Serenity мы используем Step Libraries, чтобы добавить слой абстракции между «что» и «как» в наших приемочных тестах. Определения шагов Cucumber описывают, «что» делает приемочный тест, в достаточно нейтральных для реализации условиях, благоприятных для бизнеса. Таким образом, мы говорим «ищет предметы, содержащие « шерсть », а не« входит в шерсть »«в поле поиска и нажимает на кнопку поиска». Этот многоуровневый подход облегчает понимание и сопровождение тестов и помогает создать большую библиотеку повторяющихся шагов бизнес-уровня, которые мы можем использовать в других тестах. Без этого В качестве многоуровневого подхода определения шагов имеют тенденцию очень быстро становиться очень техническими, что ограничивает повторное использование и затрудняет их понимание и поддержку.
Файлы определений шагов должны находиться внутри или под пакетом, содержащим бегуны сценария:
|----src | |----test | | |----java | | | |----net | | | | |----serenity_bdd | | | | | |----samples | | | | | | |----etsy | | | | | | | |----features | | | | | | | | |----AcceptanceTests.java | | | | | | | | |----steps | | | | | | | | | |----SearchByKeywordStepDefinitions.java | | | | | | | | | |----serenity | | | | | | | | | | |----BuyerSteps.java
Пакет бегуна сценария |
Сценарист бегун |
Определения шагов для участников сценария |
Библиотеки Serenity Step находятся в другом подпакете. |
3.4. Библиотеки «Шаг безмятежности»
Библиотека шагов Serenity — это обычный Java-класс с методами, помеченными @Step
аннотацией, как показано здесь:
public class BuyerSteps { HomePage homePage; SearchResultsPage searchResultsPage; @Step public void opens_etsy_home_page() { homePage.open(); } @Step public void searches_for_items_containing(String keywords) { homePage.searchFor(keywords); } @Step public void should_see_items_related_to(String keywords) { List<String> resultTitles = searchResultsPage.getResultTitles(); resultTitles.stream().forEach(title -> assertThat(title.contains(keywords))); } } //end:tail
Библиотеки шагов часто используют объекты Page Objects, которые автоматически создаются |
В @Step аннотации указан метод, который будет отображаться как шаг в отчетах о тестировании. |
В этих определениях шагов реализовано «что» за «как» шагов «задано когда». Однако, как и в любом хорошо написанном коде, определения шагов не должны быть слишком сложными и должны фокусироваться на работе на одном уровне. абстракция. Определения шагов обычно организуют вызовы к более техническим уровням, таким как веб-службы, базы данных или объекты страниц WebDriver. Например, в таких автоматизированных веб-тестах методы библиотеки шагов не вызывают непосредственно WebDriver, а скорее взаимодействуют с Объекты страницы .
3.5. Объекты страницы
Объекты страницы содержат информацию о том, как тест взаимодействует с определенной веб-страницей. Они скрывают детали реализации WebDriver о том, как элементы на странице доступны и управляются с помощью более удобных для бизнеса методов. Подобно шагам, объекты Page являются повторно используемыми компонентами, которые облегчают понимание и обслуживание тестов.
Serenity автоматически создает экземпляры Page Objects для вас и внедряет текущий экземпляр WebDriver. Все, что вам нужно беспокоиться, это код WebDriver, который взаимодействует со страницей. И Serenity предлагает несколько быстрых клавиш, чтобы сделать это проще. Например, вот объект страницы для домашней страницы:
@DefaultUrl("http://www.etsy.com") public class HomePage extends PageObject { @FindBy(css = "button[value='Search']") WebElement searchButton; public void searchFor(String keywords) { $("#search-query").sendKeys(keywords); searchButton.click(); } }
Какой URL должен использоваться по умолчанию при вызове open() метода |
Объект страницы Serenity должен расширять PageObject класс |
Вы можете использовать $ метод для прямого доступа к элементам с помощью выражений CSS или XPath. |
Или вы можете использовать переменную-член с @FindBy аннотацией |
И вот второй объект страницы, который мы используем:
public class SearchResultsPage extends PageObject { @FindBy(css=".listing-card") List<WebElement> listingCards; public List<String> getResultTitles() { return listingCards.stream() .map(element -> element.getText()) .collect(Collectors.toList()); } } // end:tail[]
В обоих случаях мы скрываем реализацию WebDriver от способа доступа к элементам страницы внутри методов объекта страницы. Это делает код более легким для чтения и уменьшает количество мест, которые необходимо изменить, если страница изменена.
4. Отчетная и живая документация
Отчетность — одна из сильных сторон Серенити. Serenity не только сообщает о том, прошел ли тест или нет, но и документирует, что он сделал, в пошаговом описательном формате, который включает в себя данные теста и снимки экрана для веб-тестов. Например, следующая страница иллюстрирует результаты теста для наших первых критериев приемлемости:
Рисунок 1. Результаты теста, представленные в Serenity
Обратите внимание, как этот отчет точно воспроизводит пример из беседы с бизнесом, а также дает возможность перейти к «что», чтобы увидеть, как был выполнен определенный шаг, и (в данном случае), как выглядят соответствующие снимки экрана. как.
Ранее мы видели, как примеры таблиц могут быть отличным способом обобщить бизнес-логику; важно, чтобы эти таблицы были отражены в результатах испытаний, как показано здесь:
Рисунок 2. Результаты теста с таблицей примеров в Serenity
Но результаты тестов являются лишь частью картины. Также важно знать, какая работа была проделана и какая работа в процессе. При использовании Cucumber любой сценарий, содержащий шаги без соответствующих методов определения шагов, будет отображаться в отчетах как Ожидание (синий на графиках):
Рисунок 3. Обзор результатов теста
В предыдущем разделе мы увидели, как файлы объектов были организованы в каталоги, которые представляют функции или возможности более высокого уровня. Serenity будет использовать эту структуру пакета для группировки и агрегирования результатов тестирования для каждой функции. Таким образом, Serenity может сообщить о том, насколько хорошо было протестировано каждое требование, а также рассказать о требованиях, которые не были протестированы:
Рисунок 4. Отчеты о безопасности и требованиях
5. Вывод
Надеюсь, этого будет достаточно, чтобы вы почувствовали вкус Serenity и Cucumber-JVM.
Тем не менее, мы едва нацарапали поверхность того, что Serenity может сделать для ваших автоматических приемочных тестов. Вы можете прочитать больше о Serenity и о принципах, лежащих в его основе, читая Руководство пользователя или читая BDD в действии , где эти главы посвящены нескольким главам. И не забудьте проверить онлайн-курсы в Parleys .
Вы можете получить исходный код проекта, обсуждаемого в этой статье на GitHub .