«1. Введение
Хуки Cucumber могут пригодиться, когда мы хотим выполнить определенные действия для каждого сценария или шага, но без явного указания этих действий в коде Gherkin.
В этом уроке мы рассмотрим хуки @Before, @BeforeStep, @AfterStep и @After Cucumber.
2. Обзор хуков в Cucumber
2.1. Когда следует использовать хуки?
Хуки можно использовать для выполнения фоновых задач, не являющихся частью бизнес-функций. Такими задачами могут быть:
-
Запуск браузера Настройка или очистка файлов cookie Подключение к базе данных Проверка состояния системы Мониторинг
Примером использования для мониторинга может быть обновление информационной панели с ходом теста в режиме реального времени.
Хуки не видны в коде Gherkin. Поэтому мы не должны рассматривать их как замену огуречного фона или заданного шага.
Мы рассмотрим пример, в котором мы используем хуки для создания скриншотов во время выполнения теста.
2.2. Объем хуков
Хуки влияют на каждый сценарий. Поэтому рекомендуется определять все хуки в выделенном классе конфигурации.
Нет необходимости определять одни и те же хуки в каждом классе связующего кода. Если мы определим хуки в том же классе, что и наш связующий код, у нас будет менее читаемый код.
3. Хуки
Давайте сначала посмотрим на отдельные хуки. Затем мы рассмотрим полный пример, где мы увидим, как хуки выполняются при объединении.
3.1. @Before
Методы, аннотированные @Before, будут выполняться перед каждым сценарием. В нашем примере мы будем запускать браузер перед каждым сценарием:
@Before
public void initialization() {
startBrowser();
}
Если мы аннотируем несколько методов с помощью @Before, мы можем явно определить порядок выполнения шагов:
@Before(order=2)
public void beforeScenario() {
takeScreenshot();
}
вышеприведенный метод выполняется вторым, так как мы передаем 2 в качестве значения параметра порядка в аннотацию. Мы также можем передать 1 в качестве значения параметра порядка нашего метода инициализации:
@Before(order=1)
public void initialization()
Итак, когда мы выполняем сценарий, сначала выполняется initialization(), а потом — beforeScenario().
3.2. @BeforeStep
Методы, аннотированные @BeforeStep, выполняются перед каждым шагом. Давайте воспользуемся аннотацией, чтобы делать скриншоты перед каждым шагом:
@BeforeStep
public void beforeStep() {
takeScreenshot();
}
3.3. @AfterStep
Методы, аннотированные @AfterStep, выполняются после каждого шага:
@AfterStep
public void afterStep() {
takeScreenshot();
}
Здесь мы использовали @AfterStep, чтобы делать снимки экрана после каждого шага. Это происходит независимо от того, завершается шаг успешно или нет.
3.4. @After
Методы, аннотированные @After, выполняются после каждого сценария:
@After
public void afterScenario() {
takeScreenshot();
closeBrowser();
}
В нашем примере мы сделаем последний снимок экрана и закроем браузер. Это происходит независимо от того, успешно ли завершился сценарий.
3.5. Параметр сценария
Методы, аннотированные аннотацией ловушки, могут принимать параметр типа Scenario:
@After
public void beforeScenario(Scenario scenario) {
// some code
}
Объект типа Scenario содержит информацию о текущем сценарии. Включены имя сценария, количество шагов, имена шагов и статус (пройдено или не пройдено). Это может быть полезно, если мы хотим выполнять разные действия для пройденных и не пройденных тестов.
4. Выполнение хуков
4.1. Happy Flow
Давайте теперь посмотрим, что происходит, когда мы запускаем сценарий Cucumber со всеми четырьмя типами хуков:
Feature: Book Store With Hooks
Background: The Book Store
Given The following books are available in the store
| The Devil in the White City | Erik Larson |
| The Lion, the Witch and the Wardrobe | C.S. Lewis |
| In the Garden of Beasts | Erik Larson |
Scenario: 1 - Find books by author
When I ask for a book by the author Erik Larson
Then The salesperson says that there are 2 books
Scenario: 2 - Find books by author, but isn't there
When I ask for a book by the author Marcel Proust
Then The salesperson says that there are 0 books
Глядя на результат тестового запуска в IntelliJ IDE, мы видим порядок выполнения:
Сначала выполняются два наших хука @Before. Затем до и после каждого шага запускаются хуки @BeforeStep и @AfterStep соответственно. Наконец, запускается хук @After. Все хуки выполняются для обоих сценариев.
4.2. Несчастливый поток: шаг не пройден
Давайте посмотрим, что произойдет, если шаг не пройден. Как видно на снимке экрана ниже, выполняются хуки @Before и @After неудачного шага. Последующие шаги пропускаются, и, наконец, выполняется хук @After:
Поведение @After аналогично действию finally-clause после try-catch в Java. Мы могли бы использовать его для выполнения задач очистки, если шаг не удался. В нашем примере мы по-прежнему делаем снимок экрана, даже если сценарий не работает.
4.3. Несчастливый поток: хук не работает
«Давайте посмотрим, что происходит, когда выходит из строя сам хук. В приведенном ниже примере первый @BeforeStep терпит неудачу.
В этом случае фактический шаг не запускается, но запускается хук @AfterStep. Последующие шаги также не будут выполняться, тогда как хук @After выполняется в конце:
5. Условное выполнение с тегами
Хуки определяются глобально и влияют на все сценарии и шаги. Однако с помощью тегов Cucumber мы можем точно определить, для каких сценариев должен выполняться хук:
@Before(order=2, value="@Screenshots")
public void beforeScenario() {
takeScreenshot();
}
Этот хук будет выполняться только для сценариев, помеченных тегом @Screenshots:
@Screenshots
Scenario: 1 - Find books by author
When I ask for a book by the author Erik Larson
Then The salesperson says that there are 2 books
6 . Java 8
Мы можем добавить поддержку Cucumber Java 8, чтобы определить все хуки с лямбда-выражениями.
Вспомним наш хук инициализации из приведенного выше примера:
@Before(order=2)
public void initialization() {
startBrowser();
}
Переписанный с лямбда-выражением, мы получаем:
public BookStoreWithHooksRunSteps() {
Before(2, () -> startBrowser());
}
То же самое работает и для @BeforeStep, @After и @AfterStep.
7. Заключение
В этой статье мы рассмотрели, как определить хуки Cucumber.
Мы обсудили, в каких случаях их следует использовать, а когда нет. Затем мы увидели, в каком порядке выполняются хуки и как мы можем добиться условного выполнения.
Наконец, мы увидели, как можно определять хуки с помощью лямбда-нотации Java 8.
Как обычно, полный исходный код этой статьи доступен на GitHub.