Cucumber: превращаем тесты в понятные бизнес-сценарии – BDD подход
Для кого эта статья:
- Тестировщики и QA специалисты, интересующиеся автоматизацией тестирования
- Разработчики, которые хотят улучшить взаимодействие с тестировщиками через BDD
Менеджеры и бизнес-аналитики, которые стремятся понять и участвовать в процессе качества продукта
Автоматизация тестирования — это не роскошь, а необходимость в мире, где релизы происходят ежедневно, а качество продукта должно оставаться на высоте. Cucumber — инструмент, который превращает сухие технические тесты в понятные бизнес-сценарии, где даже неподготовленный заказчик может разобраться, что именно тестируется. Этот фреймворк стал золотым стандартом в BDD-подходе, соединяя технических и нетехнических специалистов на языке конкретных примеров и ожидаемых результатов. Готовы погрузиться в мир, где тесты читаются как истории? 🥒
Хотите освоить Cucumber и другие передовые инструменты автоматизации тестирования? Курс тестировщика ПО от Skypro предлагает погружение в практический BDD-подход с использованием реальных проектов. Вы не просто изучите теорию, а создадите собственные автотесты на Cucumber, которые можно будет добавить в портфолио. Наши эксперты-практики покажут, как превратить описание на обычном языке в работающие тесты и интегрировать их в CI/CD-пайплайн.
Тестирование с Cucumber: обзор BDD-подхода
Cucumber — это инструмент, реализующий методологию Behavior-Driven Development (BDD), которая фокусируется на поведении системы с точки зрения бизнеса. Вместо написания тестов в традиционном формате, BDD предлагает описывать ожидаемое поведение системы на естественном языке, используя формат "Дано-Когда-Тогда" (Given-When-Then).
Основная идея BDD заключается в том, что разработка должна начинаться с понимания бизнес-требований и ожиданий пользователей. Cucumber позволяет записывать эти ожидания в виде сценариев на языке Gherkin, который понятен как техническим специалистам, так и представителям бизнеса.
Ключевые преимущества BDD-подхода с использованием Cucumber:
- Единый язык для общения между разработчиками, тестировщиками и бизнес-аналитиками
- Документация, которая всегда актуальна и исполняема в виде тестов
- Фокус на бизнес-ценности каждой функциональности
- Раннее выявление несоответствий в понимании требований
- Возможность автоматизации тестирования на основе бизнес-сценариев
BDD-подход кардинально меняет процесс тестирования, перенося фокус с "как это работает" на "что это должно делать". Это особенно ценно в Agile-проектах, где требования могут меняться, а постоянная коммуникация между всеми участниками процесса критически важна.
Алексей Петров, Lead QA Engineer Когда мы внедрили Cucumber в нашу команду, первое время возникало много сопротивления. Разработчики не понимали, зачем писать тесты дважды — сначала на Gherkin, а потом реализовывать их на Java. Переломный момент наступил на демонстрации заказчику. Мы показали не только работающую функциональность, но и сценарии на Gherkin, описывающие, что именно мы протестировали. Представитель заказчика буквально сказал: "Впервые я вижу тесты, которые я могу прочитать и понять". После этого сопротивление исчезло — стало очевидно, что Cucumber создаёт ценность не только для технической команды, но и для бизнеса.
| Традиционное тестирование | BDD с Cucumber |
|---|---|
| Фокус на технических деталях | Фокус на поведении системы |
| Тесты понятны только техническим специалистам | Тесты понятны всем участникам проекта |
| Документация отделена от кода | Живая документация в виде исполняемых спецификаций |
| Сложно отследить соответствие тестов бизнес-требованиям | Прямая связь между требованиями и тестами |
| Разработка и тестирование часто разделены | Совместная работа над определением поведения системы |

Настройка Cucumber для автоматизации тестов
Начать работу с Cucumber проще, чем кажется, но важно правильно настроить среду разработки. Рассмотрим пошаговый процесс настройки Cucumber для Java-проекта, хотя принципы остаются схожими и для других языков программирования. 🛠️
Шаг 1: Добавление зависимостей
Для Maven-проекта добавьте следующие зависимости в файл pom.xml:
<dependencies>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>7.11.1</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>7.11.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
</dependencies>
Шаг 2: Создание структуры проекта
Стандартная структура проекта с Cucumber включает:
src/test/resources/features/— каталог для feature-файлов с Gherkin-сценариямиsrc/test/java/steps/— каталог для степ-дефинишенов (реализаций шагов)src/test/java/runners/— каталог для runner-классов, запускающих тесты
Шаг 3: Создание базового runner-класса
package runners;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(
features = "src/test/resources/features",
glue = {"steps"},
plugin = {"pretty", "html:target/cucumber-reports"}
)
public class TestRunner {
}
Шаг 4: Настройка IDE
Для удобной работы с Cucumber установите плагины в вашу IDE:
- Для IntelliJ IDEA — Cucumber for Java и Gherkin
- Для Eclipse — Cucumber Eclipse Plugin
- Для VS Code — Cucumber (Gherkin) Full Support
Мария Соколова, QA Automation Engineer Моя первая настройка Cucumber оказалась настоящим испытанием. Я добавила зависимости, создала структуру проекта, но тесты упорно не запускались. Сообщения об ошибках были малоинформативными, и я потратила целый день на отладку. Проблема оказалась в несоответствии версий — я использовала Cucumber 6.x с JUnit 5, что требовало дополнительных настроек. Когда я перешла на согласованные версии библиотек и правильно настроила runner-класс, всё заработало как по маслу. Этот опыт научил меня всегда проверять совместимость версий и начинать с простейшего рабочего примера, постепенно усложняя его.
Шаг 5: Настройка параметров запуска
Cucumber предоставляет гибкие возможности конфигурации через CucumberOptions:
| Параметр | Описание | Пример использования |
|---|---|---|
| features | Путь к feature-файлам | features = "src/test/resources/features" |
| glue | Пакеты со степ-дефинишенами | glue = {"steps", "hooks"} |
| tags | Теги для фильтрации сценариев | tags = "@smoke or @regression" |
| plugin | Плагины для генерации отчётов | plugin = {"pretty", "json:target/cucumber.json"} |
| dryRun | Проверка степ-дефинишенов без запуска тестов | dryRun = true |
| monochrome | Форматирование вывода для лучшей читаемости | monochrome = true |
Для более продвинутой настройки можно использовать файл cucumber.properties в каталоге src/test/resources, который позволяет задать глобальные параметры, не изменяя код.
Поздравляю, базовая настройка Cucumber завершена! Теперь можно переходить к созданию тестовых сценариев. 🎉
Создание эффективных сценариев на языке Gherkin
Gherkin — это язык для описания поведения системы, который используется в Cucumber. Его главная особенность — читаемость как для технических специалистов, так и для бизнес-пользователей. Эффективные сценарии на Gherkin позволяют точно определить, что должна делать система, и служат как исполняемая документация. 📝
Анатомия Gherkin-сценария
Основные компоненты сценария на Gherkin:
Feature: Функциональность, которую вы тестируете
Scenario: Конкретный сценарий использования
Given предварительное условие
When действие пользователя
Then ожидаемый результат
Ключевые слова Gherkin
- Feature — описывает тестируемую функциональность
- Scenario — конкретный тестовый сценарий
- Given — предварительные условия
- When — действия пользователя или системы
- Then — проверяемый результат
- And, But — для добавления дополнительных шагов
- Background — общие шаги для всех сценариев в feature-файле
- Scenario Outline — шаблон сценария с примерами
- Examples — таблица примеров для Scenario Outline
- @tags — метки для фильтрации сценариев
Принципы создания эффективных сценариев
- Фокус на бизнес-ценности — каждый сценарий должен проверять конкретное бизнес-требование
- Независимость — сценарии должны быть автономными и не зависеть от результатов других тестов
- Атомарность — один сценарий должен проверять одну функцию или аспект поведения
- Понятность — используйте бизнес-терминологию вместо технических деталей
- Лаконичность — избегайте избыточных шагов и повторений
Пример плохого сценария:
Feature: Веб-сайт
Scenario: Тест логина
Given я открыл браузер
And я перешел на страницу логина
When я ввел "admin" в поле username
And я ввел "password123" в поле password
And я нажал кнопку Submit
Then я вижу домашнюю страницу
And я вижу имя пользователя в правом верхнем углу
When я нажимаю на ссылку профиля
Then я вижу страницу профиля
Пример хорошего сценария:
Feature: Аутентификация пользователя
Как зарегистрированный пользователь
Я хочу войти в систему
Чтобы получить доступ к моим персональным данным
Scenario: Успешный вход в систему с корректными учетными данными
Given пользователь находится на странице входа
When пользователь вводит корректные учетные данные
And нажимает кнопку "Войти"
Then система авторизует пользователя
And перенаправляет на домашнюю страницу
Использование параметров в шагах
Для повышения гибкости сценариев используйте параметры:
Scenario: Вход с разными учетными данными
Given пользователь находится на странице входа
When пользователь вводит имя "admin" и пароль "admin123"
Then система отображает приветственное сообщение "Привет, Администратор"
Сценарии с таблицами данных
Для тестирования с разными наборами данных используйте Scenario Outline и Examples:
Scenario Outline: Вход с разными учетными данными
Given пользователь находится на странице входа
When пользователь вводит имя "<username>" и пароль "<password>"
Then система отображает сообщение "<message>"
Examples:
| username | password | message |
| admin | admin123 | Привет, Администратор |
| user | user123 | Привет, Пользователь |
| invalid | wrong | Неверные учетные данные |
Организация сценариев с помощью тегов
Используйте теги для группировки сценариев и выборочного запуска:
@login @smoke
Scenario: Успешный вход в систему
...
@login @regression
Scenario: Вход с неверным паролем
...
@profile @smoke
Scenario: Просмотр профиля пользователя
...
Теги позволяют запускать только определенные группы тестов, например, только смоук-тесты или тесты определенной функциональности.
Создание эффективных сценариев на Gherkin — это искусство балансирования между технической точностью и бизнес-ориентированностью. Хорошо написанные сценарии служат как документация, средство коммуникации и автоматизированные тесты одновременно. 🚀
Написание и организация степ-дефинишенов
Степ-дефинишены (step definitions) — это код, который связывает описание шагов в Gherkin с реальными действиями, которые должна выполнить система. Это мост между человекочитаемыми сценариями и исполняемым кодом. 🔄
Структура степ-дефинишена
В Java степ-дефинишены выглядят примерно так:
@Given("пользователь находится на странице входа")
public void userIsOnLoginPage() {
driver.get("https://example.com/login");
assertEquals("Вход в систему", driver.getTitle());
}
@When("пользователь вводит имя {string} и пароль {string}")
public void userEntersCredentials(String username, String password) {
driver.findElement(By.id("username")).sendKeys(username);
driver.findElement(By.id("password")).sendKeys(password);
}
@Then("система отображает приветственное сообщение {string}")
public void systemDisplaysWelcomeMessage(String message) {
String actualMessage = driver.findElement(By.id("welcome-message")).getText();
assertEquals(message, actualMessage);
}
Типы параметров в степ-дефинишенах
Cucumber поддерживает различные типы параметров:
- {string} — для строковых параметров в кавычках
- {int} — для целочисленных значений
- {float} — для чисел с плавающей точкой
- {word} — для одиночных слов без кавычек
- {} — для произвольного текста
Организация степ-дефинишенов
Существует несколько подходов к организации степ-дефинишенов:
| Подход | Описание | Преимущества | Недостатки |
|---|---|---|---|
| По feature-файлам | Отдельный класс степов для каждого feature-файла | Логичная структура, легко найти нужные степы | Возможное дублирование кода |
| По функциональным областям | Группировка степов по функциональным областям | Хорошая модульность, возможность повторного использования | Может быть сложно найти связь с конкретными сценариями |
| По типу действий | Группировка по типу действий (UI, API, БД и т.д.) | Чёткое разделение ответственности | Шаги для одного сценария могут быть разбросаны по разным классам |
| Смешанный подход | Комбинация предыдущих подходов | Гибкость, адаптация к конкретному проекту | Требует чёткого соглашения о структуре |
Лучшие практики для степ-дефинишенов
- Единая ответственность — каждый степ должен выполнять только одно логическое действие
- Повторное использование — создавайте универсальные шаги, которые можно использовать в разных сценариях
- Абстракция деталей — скрывайте технические детали реализации от пользователя Gherkin
- Правильный уровень грануляции — избегайте как слишком крупных, так и слишком мелких шагов
- Понятные сообщения об ошибках — обеспечьте информативность при сбое теста
Использование регулярных выражений
Для более сложных сопоставлений шагов можно использовать регулярные выражения:
@Given("^пользователь с id (\\d+) и именем \"([^\"]*)\"$")
public void userWithIdAndName(int id, String name) {
// Реализация шага
}
Работа с таблицами данных
Cucumber позволяет передавать таблицы данных из Gherkin в степ-дефинишены:
Scenario: Добавление нескольких товаров в корзину
Given пользователь авторизован
When пользователь добавляет следующие товары в корзину
| Наименование | Количество | Цена |
| Смартфон | 1 | 30000 |
| Чехол | 2 | 1000 |
| Защитное стекло| 1 | 500 |
Then общая стоимость корзины составляет 32500
Соответствующий степ-дефинишен:
@When("пользователь добавляет следующие товары в корзину")
public void addProductsToCart(DataTable dataTable) {
List<Map<String, String>> products = dataTable.asMaps();
for (Map<String, String> product : products) {
String name = product.get("Наименование");
int quantity = Integer.parseInt(product.get("Количество"));
int price = Integer.parseInt(product.get("Цена"));
cart.addProduct(name, quantity, price);
}
}
Хуки в Cucumber
Хуки позволяют выполнять код до и после сценариев:
@Before
public void setup() {
// Код, выполняемый перед каждым сценарием
}
@After
public void tearDown() {
// Код, выполняемый после каждого сценария
}
@Before("@database")
public void setupDatabaseConnection() {
// Код, выполняемый только перед сценариями с тегом @database
}
Переиспользование шагов
Для повышения эффективности создавайте методы, которые могут вызываться из разных степ-дефинишенов:
private void login(String username, String password) {
driver.findElement(By.id("username")).sendKeys(username);
driver.findElement(By.id("password")).sendKeys(password);
driver.findElement(By.id("login-button")).click();
}
@Given("пользователь авторизован как администратор")
public void adminIsLoggedIn() {
driver.get(loginPageUrl);
login("admin", "adminPassword");
}
@Given("пользователь авторизован как обычный пользователь")
public void regularUserIsLoggedIn() {
driver.get(loginPageUrl);
login("user", "userPassword");
}
Хорошо организованные степ-дефинишены делают тесты более понятными, поддерживаемыми и расширяемыми. Они являются ключевым элементом успешного внедрения BDD с Cucumber. 🧩
Интеграция Cucumber с другими инструментами тестирования
Cucumber становится еще мощнее, когда интегрируется с другими инструментами тестирования, образуя комплексную экосистему для автоматизации. Рассмотрим основные варианты интеграции, которые помогут вывести ваше тестирование на новый уровень. 🔄
Интеграция с Selenium WebDriver
Selenium — самый популярный инструмент для автоматизации тестирования веб-приложений, который отлично работает с Cucumber:
@Given("пользователь находится на странице входа")
public void userOnLoginPage() {
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://example.com/login");
}
@When("пользователь вводит корректные учетные данные")
public void userEntersCredentials() {
driver.findElement(By.id("username")).sendKeys("testuser");
driver.findElement(By.id("password")).sendKeys("password");
driver.findElement(By.id("login-button")).click();
}
@Then("система авторизует пользователя")
public void userIsAuthorized() {
WebElement welcomeMessage = driver.findElement(By.id("welcome"));
assertTrue(welcomeMessage.isDisplayed());
}
Интеграция с RestAssured для API-тестирования
RestAssured — библиотека для тестирования REST API, которая хорошо сочетается с Cucumber:
@Given("API сервис доступен")
public void apiServiceIsAvailable() {
RestAssured.baseURI = "https://api.example.com";
}
@When("отправляется GET запрос к эндпоинту {string}")
public void sendGetRequest(String endpoint) {
response = RestAssured.given()
.contentType(ContentType.JSON)
.when()
.get(endpoint);
}
@Then("код ответа должен быть {int}")
public void verifyResponseCode(int expectedStatusCode) {
response.then().statusCode(expectedStatusCode);
}
Интеграция с CI/CD системами
Cucumber-тесты можно интегрировать в CI/CD-пайплайны, например, с помощью Jenkins:
- Используйте плагин Cucumber Reports для Jenkins для визуализации результатов тестов
- Настройте автоматический запуск тестов при коммите или по расписанию
- Добавьте параметры запуска для выборочного выполнения тестов с определенными тегами
Пример конфигурации Jenkins Pipeline:
pipeline {
agent any
stages {
stage('Checkout') {
steps {
git 'https://github.com/your-repo/your-project.git'
}
}
stage('Build') {
steps {
sh 'mvn clean compile'
}
}
stage('Test') {
steps {
sh 'mvn test -Dcucumber.filter.tags="@smoke"'
}
}
}
post {
always {
cucumber buildStatus: 'UNSTABLE',
reportTitle: 'Cucumber Report',
fileIncludePattern: '**/cucumber.json',
trendsLimit: 10
}
}
}
Интеграция с системами управления тестированием
Cucumber можно интегрировать с такими системами, как TestRail, Zephyr или JIRA:
- Добавляйте ID тест-кейсов в теги сценариев:
@TR-1234 - Используйте специальные плагины для отправки результатов тестов в системы управления тестированием
- Автоматизируйте обновление статуса тестов на основе результатов выполнения
Интеграция с базами данных
Для тестов, требующих взаимодействия с базой данных:
@Given("в базе данных есть пользователь с именем {string}")
public void userExistsInDatabase(String username) {
try (Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword)) {
PreparedStatement stmt = conn.prepareStatement(
"INSERT INTO users (username, email, active) VALUES (?, ?, ?)");
stmt.setString(1, username);
stmt.setString(2, username + "@example.com");
stmt.setBoolean(3, true);
stmt.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException("Ошибка при работе с БД", e);
}
}
Интеграция с библиотеками отчетов
Для создания информативных отчетов используйте:
- Extent Reports — для создания красивых HTML-отчетов
- Allure — для детальных и интерактивных отчетов о тестировании
Пример настройки Allure для Cucumber:
@RunWith(Cucumber.class)
@CucumberOptions(
features = "src/test/resources/features",
glue = {"steps"},
plugin = {
"pretty",
"io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm"
}
)
public class TestRunner {
}
Интеграция с инструментами мониторинга производительности
Для тестирования производительности Cucumber можно интегрировать с:
- JMeter — через плагины или API
- Gatling — для нагрузочного тестирования
- New Relic или Datadog — для мониторинга производительности во время тестов
Интеграция с облачными платформами для тестирования
Для запуска тестов в облаке используйте:
- BrowserStack или Sauce Labs — для тестирования на различных браузерах и устройствах
- AWS Device Farm — для тестирования на реальных мобильных устройствах
Пример интеграции с BrowserStack:
@Before
public void setup() {
String USERNAME = System.getenv("BROWSERSTACK_USERNAME");
String ACCESS_KEY = System.getenv("BROWSERSTACK_ACCESS_KEY");
String URL = "https://" + USERNAME + ":" + ACCESS_KEY + "@hub-cloud.browserstack.com/wd/hub";
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("browserName", "Chrome");
capabilities.setCapability("browser_version", "latest");
capabilities.setCapability("os", "Windows");
capabilities.setCapability("os_version", "10");
capabilities.setCapability("name", "BStack-[Java] Sample Test");
try {
driver = new RemoteWebDriver(new URL(URL), capabilities);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
Интеграция Cucumber с другими инструментами тестирования создает мощную экосистему, которая охватывает все аспекты качества программного обеспечения: от функциональности до производительности, от UI до API. Правильно выбранные инструменты и их интеграция значительно повышают эффективность тестирования и ценность BDD-подхода для всей команды. 🚀
Тестирование с Cucumber — это не просто автоматизация, это философия совместной работы над качеством. Освоив основы BDD-подхода, научившись писать выразительные Gherkin-сценарии и эффективно организовывать степ-дефинишены, вы создаёте не просто тесты, а живую документацию, понятную всем участникам процесса. Интеграция с другими инструментами расширяет возможности, но истинная сила Cucumber в объединении людей вокруг общего понимания того, что должна делать ваша система. Помните — лучшие тесты рассказывают историю, которую понимает каждый.