Что такое BDD?
Behavior-Driven Development (BDD) — практика совместной работы, преодолевающая разрыв между бизнес-стейкхолдерами, разработчиками и тестировщиками. Она использует структурированный естественный язык Gherkin для описания ожидаемого поведения системы.
Центральная идея: определить что должна делать система (поведение) до реализации как она это делает (код).
Синтаксис Gherkin
Gherkin использует три основных ключевых слова:
- Given — предусловие (начальное состояние)
- When — действие (что делает пользователь)
- Then — ожидаемый результат (что должно произойти)
Пример Feature-файла
# features/login.feature
Feature: Авторизация пользователя
Как зарегистрированный пользователь
Я хочу войти в свой аккаунт
Чтобы получить доступ к дашборду
Scenario: Успешный вход с валидными данными
Given я на странице логина
When я ввожу "admin@test.com" как email
And я ввожу "secret123" как пароль
And я нажимаю кнопку входа
Then я должен быть перенаправлен на дашборд
And я должен видеть "Добро пожаловать, Admin" как приветствие
Scenario: Неудачный вход с неверным паролем
Given я на странице логина
When я ввожу "admin@test.com" как email
And я ввожу "wrongpassword" как пароль
And я нажимаю кнопку входа
Then я должен видеть сообщение об ошибке "Неверные учётные данные"
And я должен остаться на странице логина
Scenario Outline (Data-Driven BDD)
Scenario Outline: Вход с различными учётными данными
Given я на странице логина
When я ввожу "<email>" как email
And я ввожу "<password>" как пароль
And я нажимаю кнопку входа
Then я должен видеть "<результат>"
Examples:
| email | password | результат |
| admin@test.com | secret123 | Добро пожаловать, Admin |
| editor@test.com | pass456 | Добро пожаловать, Editor |
| wrong@test.com | wrong | Неверные учётные данные |
| | secret123 | Email обязателен |
Step Definitions
Step definitions связывают шаги Gherkin с кодом автоматизации:
const { Given, When, Then } = require('@cucumber/cucumber');
const { expect } = require('@playwright/test');
Given('я на странице логина', async function () {
await this.page.goto('/login');
});
When('я ввожу {string} как email', async function (email) {
await this.page.fill('[data-testid="email"]', email);
});
When('я ввожу {string} как пароль', async function (password) {
await this.page.fill('[data-testid="password"]', password);
});
When('я нажимаю кнопку входа', async function () {
await this.page.click('[data-testid="login-submit"]');
});
Then('я должен быть перенаправлен на дашборд', async function () {
await expect(this.page).toHaveURL('/dashboard');
});
Then('я должен видеть {string} как приветствие', async function (greeting) {
await expect(this.page.locator('.welcome-msg')).toHaveText(greeting);
});
Then('я должен видеть сообщение об ошибке {string}', async function (message) {
await expect(this.page.locator('.error-message')).toHaveText(message);
});
Написание хорошего Gherkin
Бизнес-язык, не технический
# Плохо — слишком технично
Scenario: Тест логина
Given я перехожу на "https://app.example.com/login"
When я заполняю "#email" значением "admin@test.com"
And я кликаю "#login-btn"
# Хорошо — бизнес-поведение
Scenario: Успешный вход
Given я зарегистрированный пользователь-админ
When я вхожу с валидными данными
Then я должен видеть свой дашборд
Декларативный стиль вместо императивного
# Императивный (слишком много шагов)
Scenario: Покупка товара
Given я открываю браузер
And я перехожу на главную страницу
And я кликаю на "Товары"
And я ищу "Беспроводная мышь"
And я кликаю на первый результат
And я кликаю "Добавить в корзину"
# Декларативный (понятное поведение)
Scenario: Покупка товара
Given я авторизован как покупатель
When я добавляю "Беспроводная мышь" в корзину
And я завершаю оформление сохранённым способом оплаты
Then я должен получить подтверждение заказа
Теги для организации
@smoke @login
Feature: Авторизация пользователя
@positive @critical
Scenario: Успешный вход
Given я на странице логина
When я вхожу с валидными данными
Then я должен видеть дашборд
@negative
Scenario: Вход с заблокированным аккаунтом
Given мой аккаунт заблокирован
When я пытаюсь войти
Then я должен видеть сообщение о блокировке
Запуск с тегами:
npx cucumber-js --tags "@smoke"
npx cucumber-js --tags "@smoke and not @negative"
BDD с Playwright-BDD
Playwright-BDD интегрирует синтаксис Gherkin напрямую с Playwright:
import { createBdd } from 'playwright-bdd';
const { Given, When, Then } = createBdd();
Given('я на странице логина', async ({ page }) => {
await page.goto('/login');
});
When('я вхожу с {string} и {string}', async ({ page }, email, password) => {
await page.fill('#email', email);
await page.fill('#password', password);
await page.click('#submit');
});
Then('я должен видеть дашборд', async ({ page }) => {
await page.waitForURL('/dashboard');
});
Hooks для Setup и Teardown
const { Before, After } = require('@cucumber/cucumber');
Before(async function (scenario) {
console.log(`Запуск: ${scenario.pickle.name}`);
this.page = await this.browser.newPage();
});
After(async function (scenario) {
if (scenario.result.status === 'FAILED') {
await this.page.screenshot({
path: `screenshots/${scenario.pickle.name}.png`
});
}
await this.page.close();
});
Анти-паттерны BDD
1. Написание Features после кода
BDD — инструмент совместной работы. Писать features после реализации — значит упускать суть.
2. Слишком много сценариев
Feature с 50 сценариями — знак чрезмерной детализации. Стремитесь к 5-15 сценариям на feature.
3. Cucumber только как инструмент тестирования
BDD — про совместную работу, не только автоматизацию. Если только QA пишет Gherkin, главная польза теряется.
4. Хрупкие Step Definitions
Step definitions, привязанные к конкретным UI-элементам, ломаются при изменении UI. Используйте page objects внутри step definitions.
Встреча «Три Амиго»
Наибольшая ценность BDD — во встрече «Three Amigos», где бизнес, разработка и QA обсуждают функциональность вместе:
- Бизнес объясняет желаемое поведение
- Разработка спрашивает о граничных случаях и технических ограничениях
- QA выявляет сценарии, которые могут быть упущены
Результат: набор Gherkin-сценариев, с которыми все согласны, ещё до написания первой строки кода.
Упражнение: Напишите BDD Feature
Создайте полный feature-файл для корзины покупок e-commerce:
- Напишите описание feature (Как… Я хочу… Чтобы…)
- Напишите 5 сценариев: добавить товар, удалить, обновить количество, применить промокод, перейти к оформлению
- Используйте Scenario Outline с Examples для разных промокодов
- Добавьте теги для smoke, regression и позитивной/негативной категоризации
- Напишите step definitions для минимум 3 сценариев с page objects
Ключевые выводы
- BDD использует Gherkin (Given/When/Then) для описания поведения на бизнес-языке
- Feature-файлы служат живой документацией, понятной всем
- Step definitions связывают Gherkin с кодом автоматизации
- Пишите декларативные сценарии о поведении, а не императивные шаги
- Встреча «Three Amigos» — где реализуется ценность совместной работы BDD
- Теги для организации и выборочного запуска сценариев