TL;DR
- Cucumber обеспечивает BDD с тестами на простом английском (Gherkin-синтаксис)
- Feature-файлы описывают поведение: Given (предусловия), When (действия), Then (результаты)
- Step definitions связывают Gherkin-шаги с реальным тестовым кодом
- Scenario Outlines позволяют data-driven тестирование с таблицами Examples
- Интегрируется с Selenium, TestNG, JUnit для полной автоматизации тестирования
Идеально для: Команд, желающих бизнес-читаемые тесты, сотрудничество между QA и стейкхолдерами Пропусти, если: Маленькая команда, где разработчики пишут все тесты (традиционное тестирование быстрее) Время чтения: 15 минут
Твои тест-кейсы в Jira. Тестовый код в репозитории. Бизнес-требования в Confluence. Никто не знает, покрывают ли тесты требования на самом деле. Каждый спринт QA объясняет одни и те же сценарии стейкхолдерам.
Cucumber устраняет этот разрыв. Тесты пишутся на простом английском. Бизнес-стейкхолдеры могут их читать. Разработчики их реализуют. Все говорят на одном языке.
Этот туториал покрывает Cucumber от основ Gherkin до интеграции с CI/CD — всё для внедрения BDD в твоей команде.
Что такое BDD?
Behavior Driven Development (BDD) — это подход к разработке, где тесты пишутся на естественном языке, описывающем бизнес-поведение. Тесты становятся живой документацией, понятной всем.
Преимущества BDD:
- Общее понимание — бизнес, QA и разработка говорят на одном языке
- Живая документация — тесты описывают текущее поведение системы
- Раннее обнаружение дефектов — требования валидируются до написания кода
- Меньше переработок — чёткие спецификации предотвращают недопонимание
Что такое Cucumber?
Cucumber — это инструмент, поддерживающий BDD через выполнение plain-text спецификаций тестов, написанных на Gherkin. Он связывает человекочитаемые сценарии с автоматизированным тестовым кодом.
Как работает Cucumber:
- Пишешь feature-файлы на Gherkin (простой английский)
- Создаёшь step definitions (код, реализующий каждый шаг)
- Запускаешь Cucumber — он сопоставляет шаги с definitions и выполняет тесты
- Получаешь отчёты, показывающие какие сценарии прошли/упали
Установка
Java (Maven)
<dependencies>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>7.15.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-testng</artifactId>
<version>7.15.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.17.0</version>
<scope>test</scope>
</dependency>
</dependencies>
JavaScript (npm)
npm install @cucumber/cucumber --save-dev
Структура проекта
src/test/
├── java/
│ └── com/example/
│ ├── steps/
│ │ └── LoginSteps.java
│ ├── pages/
│ │ └── LoginPage.java
│ └── runners/
│ └── TestRunner.java
└── resources/
└── features/
└── login.feature
Gherkin-синтаксис
Feature-файл
# login.feature
Feature: User Login
As a registered user
I want to log into my account
So that I can access my dashboard
Background:
Given the user is on the login page
Scenario: Successful login with valid credentials
When the user enters email "user@example.com"
And the user enters password "password123"
And the user clicks the login button
Then the user should see the dashboard
And the welcome message should contain "Welcome"
Scenario: Failed login with invalid password
When the user enters email "user@example.com"
And the user enters password "wrongpassword"
And the user clicks the login button
Then the user should see an error message "Invalid credentials"
Ключевые слова
| Ключевое слово | Назначение | Пример |
|---|---|---|
| Feature | Описывает тестируемую функцию | Feature: User Login |
| Scenario | Один тест-кейс | Scenario: Successful login |
| Given | Предусловия (setup) | Given the user is on the login page |
| When | Выполняемые действия | When the user clicks login |
| Then | Ожидаемые результаты | Then the dashboard is displayed |
| And/But | Дополнительные шаги | And the user is logged in |
| Background | Общие шаги для всех сценариев | Выполняется перед каждым сценарием |
Step Definitions
Базовые шаги
// LoginSteps.java
package com.example.steps;
import io.cucumber.java.en.*;
import static org.testng.Assert.*;
public class LoginSteps {
private LoginPage loginPage;
private DashboardPage dashboardPage;
@Given("the user is on the login page")
public void userIsOnLoginPage() {
loginPage = new LoginPage(driver);
loginPage.navigateTo();
}
@When("the user enters email {string}")
public void userEntersEmail(String email) {
loginPage.enterEmail(email);
}
@When("the user enters password {string}")
public void userEntersPassword(String password) {
loginPage.enterPassword(password);
}
@When("the user clicks the login button")
public void userClicksLoginButton() {
dashboardPage = loginPage.clickLogin();
}
@Then("the user should see the dashboard")
public void userShouldSeeDashboard() {
assertTrue(dashboardPage.isDisplayed());
}
@Then("the welcome message should contain {string}")
public void welcomeMessageShouldContain(String expectedText) {
String actualMessage = dashboardPage.getWelcomeMessage();
assertTrue(actualMessage.contains(expectedText));
}
@Then("the user should see an error message {string}")
public void userShouldSeeErrorMessage(String expectedError) {
String actualError = loginPage.getErrorMessage();
assertEquals(actualError, expectedError);
}
}
Scenario Outline (Data-Driven Testing)
Feature: Login Validation
Scenario Outline: Login with various credentials
Given the user is on the login page
When the user enters email "<email>"
And the user enters password "<password>"
And the user clicks the login button
Then the login result should be "<result>"
And the message should be "<message>"
Examples:
| email | password | result | message |
| user@example.com | password123 | success | Welcome back |
| admin@example.com | admin123 | success | Welcome admin |
| user@example.com | wrongpass | failure | Invalid credentials |
| | password123 | failure | Email is required |
| user@example.com | | failure | Password is required |
@Then("the login result should be {string}")
public void loginResultShouldBe(String expectedResult) {
if (expectedResult.equals("success")) {
assertTrue(dashboardPage.isDisplayed());
} else {
assertTrue(loginPage.hasError());
}
}
@Then("the message should be {string}")
public void messageShouldBe(String expectedMessage) {
String actual = getCurrentMessage();
assertEquals(actual, expectedMessage);
}
Hooks
// Hooks.java
package com.example.steps;
import io.cucumber.java.*;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class Hooks {
private static WebDriver driver;
@BeforeAll
public static void beforeAll() {
// Выполняется один раз перед всеми сценариями
System.out.println("Запуск тестового suite");
}
@Before
public void before(Scenario scenario) {
// Выполняется перед каждым сценарием
driver = new ChromeDriver();
driver.manage().window().maximize();
System.out.println("Запуск: " + scenario.getName());
}
@Before("@smoke")
public void beforeSmoke() {
// Только для сценариев с тегом @smoke
System.out.println("Запуск smoke теста");
}
@After
public void after(Scenario scenario) {
// Выполняется после каждого сценария
if (scenario.isFailed()) {
// Скриншот при падении
byte[] screenshot = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.BYTES);
scenario.attach(screenshot, "image/png", "failure-screenshot");
}
driver.quit();
}
@AfterAll
public static void afterAll() {
// Выполняется один раз после всех сценариев
System.out.println("Тестовый suite завершён");
}
public static WebDriver getDriver() {
return driver;
}
}
Теги
@regression
Feature: User Management
@smoke @critical
Scenario: Create new user
Given I am logged in as admin
When I create a new user
Then the user should be created
@slow
Scenario: Generate user report
Given I am on the reports page
When I generate a full user report
Then the report should be downloaded
Запуск тегированных сценариев
# Только smoke тесты
mvn test -Dcucumber.filter.tags="@smoke"
# Regression но не slow тесты
mvn test -Dcucumber.filter.tags="@regression and not @slow"
# smoke ИЛИ critical
mvn test -Dcucumber.filter.tags="@smoke or @critical"
Интеграция с Page Object
// LoginPage.java
public class LoginPage {
private WebDriver driver;
private WebDriverWait wait;
private By emailField = By.id("email");
private By passwordField = By.id("password");
private By loginButton = By.id("login-btn");
private By errorMessage = By.className("error");
public LoginPage(WebDriver driver) {
this.driver = driver;
this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
}
public void navigateTo() {
driver.get("https://example.com/login");
}
public void enterEmail(String email) {
wait.until(ExpectedConditions.visibilityOfElementLocated(emailField))
.sendKeys(email);
}
public void enterPassword(String password) {
driver.findElement(passwordField).sendKeys(password);
}
public DashboardPage clickLogin() {
driver.findElement(loginButton).click();
return new DashboardPage(driver);
}
public String getErrorMessage() {
return wait.until(ExpectedConditions.visibilityOfElementLocated(errorMessage))
.getText();
}
}
Test Runner
TestNG Runner
// TestRunner.java
package com.example.runners;
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
import org.testng.annotations.DataProvider;
@CucumberOptions(
features = "src/test/resources/features",
glue = "com.example.steps",
plugin = {
"pretty",
"html:target/cucumber-reports/report.html",
"json:target/cucumber-reports/report.json"
},
tags = "@smoke or @regression"
)
public class TestRunner extends AbstractTestNGCucumberTests {
@Override
@DataProvider(parallel = true)
public Object[][] scenarios() {
return super.scenarios();
}
}
Интеграция с CI/CD
GitHub Actions
name: Cucumber Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Run Cucumber tests
run: mvn test -Dcucumber.filter.tags="@smoke"
- name: Publish report
uses: actions/upload-artifact@v4
if: always()
with:
name: cucumber-report
path: target/cucumber-reports/
Cucumber с помощью ИИ
ИИ-инструменты могут помочь писать и поддерживать Cucumber-тесты.
Что ИИ делает хорошо:
- Генерация Gherkin-сценариев из user stories
- Создание step definitions из feature-файлов
- Предложение тестовых данных для scenario outlines
- Выявление недостающих edge cases
Что всё ещё требует людей:
- Определение бизнес-релевантных сценариев
- Баланс покрытия и поддерживаемости
- Валидация сценариев со стейкхолдерами
- Рефакторинг дублирующихся шагов
FAQ
Что такое Cucumber?
Cucumber — это BDD (Behavior Driven Development) инструмент для тестирования, позволяющий писать тесты на простом английском с Gherkin-синтаксисом. Feature-файлы описывают поведение приложения, которое могут понять как технические, так и нетехнические члены команды. Step definitions связывают эти человекочитаемые спецификации с реальным кодом автоматизации.
Что такое Gherkin?
Gherkin — это предметно-ориентированный язык Cucumber для написания тестовых сценариев в виде простого текста. Он использует ключевые слова Feature, Scenario, Given, When, Then для структурирования тестов в читаемом формате. Синтаксис спроектирован быть понятным всем в команде — разработчикам, QA-инженерам, продакт-менеджерам и бизнес-стейкхолдерам.
Cucumber бесплатный?
Да, Cucumber полностью бесплатен и open-source. Он доступен для множества языков программирования, включая Java, JavaScript, Ruby, Python и Kotlin. Нет платных версий или enterprise-функций — вся функциональность доступна бесплатно.
Cucumber vs Selenium — в чём разница?
Cucumber и Selenium служат разным целям и работают вместе. Cucumber определяет что тестировать через Gherkin-сценарии (спецификация). Selenium выполняет браузерную автоматизацию (исполнение). В типичной настройке Cucumber-сценарии описывают ожидаемое поведение, а step definitions используют Selenium для взаимодействия с браузером и проверки результатов.
Официальные ресурсы
Смотрите также
- Selenium Tutorial - Основы браузерной автоматизации
- TestNG Tutorial - Java testing framework
- API Testing Guide - Тестирование REST API
- Test Documentation - Написание эффективных тестовых спецификаций
