The post has been translated automatically. Original language: Russian
This is the fourth installment in a series about BDD. In the third part, "Gherkin: How to Write Good Scripts," we learned how to write down examples. In the fifth, "End-to-end example: from an idea to a green test," we'll put everything together on one function.
The scripts on Gherkin are just text by themselves. In order for them to become tests, they need to be linked to the system code. This is the last step of the BDD cycle, but not the most important one: without good discussion and good scenarios, automation will only accelerate the production of bad tests.
How it works
Behind each step of the script is a small function called step definition. The tool reads .A feature file that finds a suitable function for each line and executes it.
Python tutorial with the Behave library (conditional Cart class):
from behave import given, when, then
@given("there are {amount:d} tenge items in the basket")
def step_cart(context, amount):
context.cart = Cart(total=amount)
@when("user applies a promo code for a {percentage:d}% discount")
def step_apply(context, percentage):
context.cart.apply_promo(percentage)
@then("the order amount becomes {expected:d} tenge")
def step_total(context, expected):
assert context.cart.total == expectedPopular tools
The principle is the same everywhere: text scripts plus step code. The language and ecosystem differ.
- Cucumber: implementations for Java, JavaScript and other languages, the most famous tool in the family.
- Behave and pytest-bdd: for Python.
- Behat: for PHP.
- SpecFlow and its development for .NET.
Before choosing, check the current documentation: the status of projects and their support are changing.
At what level should scripts be run?
It is not necessary to check the behavior through the interface. The same BDD rule can be automated at different levels.:
- Through the business logic code (service layer). Fast and stable. It fits most rules.
- Via the API. It's a little slower, but it checks the system closer to real work.
- Through the UI. The slowest and most fragile option. Leave it for a few key scenarios.
The rule is: the closer to the business logic, the cheaper the support. Don't turn all scripts into interface checks.
Embedding in CI
- Run quick scripts with every commit or pull request.
- Take long end-to-end scenarios into a separate stage or a night run.
- Publish the run report in a readable form so that the business can see which rules are being followed.
- Fix errors in scripts as much as you do errors in code: the "red" test, which everyone is used to, devalues the entire system.
How to organize the steps
- Store reusable steps in common modules, but don't create "universal" steps for all occasions.
- Do not write the logic in the steps themselves: they should only invoke the system code.
- Keep an eye on the names: if the steps are called differently but do the same thing, the set will quickly get confused.
Result
Automation turns examples into regression protection and live documentation. But it requires discipline: the right level, stable steps, and a unified language. In the fifth part, "End-to-end example: from an idea to a green test," we will go through the entire cycle on one small function.
At what level do you automate behavior checks: through the UI, API, or directly through the code?
Это четвёртая часть серии о BDD. В третьей части, «Gherkin: как писать хорошие сценарии», мы научились записывать примеры. В пятой, «Сквозной пример: от идеи до зелёного теста», соберём всё вместе на одной функции.
Сценарии на Gherkin сами по себе только текст. Чтобы они стали тестами, их нужно связать с кодом системы. Это последний шаг цикла BDD, но не самый главный: без хорошего обсуждения и хороших сценариев автоматизация лишь ускорит производство плохих тестов.
Как это работает
За каждым шагом сценария стоит небольшая функция, которую называют step definition (определение шага). Инструмент читает .feature-файл, находит для каждой строки подходящую функцию и выполняет её.
Учебный пример на Python с библиотекой Behave (класс Cart условный):
from behave import given, when, then
@given("в корзине товары на сумму {amount:d} тенге")
def step_cart(context, amount):
context.cart = Cart(total=amount)
@when("пользователь применяет промокод на скидку {percent:d}%")
def step_apply(context, percent):
context.cart.apply_promo(percent)
@then("сумма заказа становится {expected:d} тенге")
def step_total(context, expected):
assert context.cart.total == expectedПопулярные инструменты
Принцип везде один: текстовые сценарии плюс код шагов. Различается язык и экосистема.
- Cucumber: реализации для Java, JavaScript и других языков, самый известный инструмент семейства.
- Behave и pytest-bdd: для Python.
- Behat: для PHP.
- SpecFlow и его развитие для .NET.
Перед выбором сверьтесь с актуальной документацией: состояние проектов и их поддержка меняются.
На каком уровне запускать сценарии
Необязательно проверять поведение через интерфейс. Одно и то же BDD-правило можно автоматизировать на разных уровнях:
- Через код бизнес-логики (сервисный слой). Быстро и стабильно. Подходит для большинства правил.
- Через API. Чуть медленнее, но проверяет систему ближе к реальной работе.
- Через UI. Самый медленный и хрупкий вариант. Оставьте его для нескольких ключевых сценариев.
Правило: чем ближе к бизнес-логике, тем дешевле поддержка. Не превращайте все сценарии в проверки интерфейса.
Встраивание в CI
- Запускайте быстрые сценарии при каждом коммите или pull request.
- Долгие сквозные сценарии выносите в отдельный этап или ночной прогон.
- Публикуйте отчёт о прогоне в читаемом виде, чтобы бизнес мог видеть, какие правила выполняются.
- Исправляйте ошибки в сценариях так же приоритетно, как ошибки в коде: «красный» тест, к которому все привыкли, обесценивает всю систему.
Как организовать шаги
- Храните переиспользуемые шаги в общих модулях, но не создавайте «универсальных» шагов на все случаи жизни.
- Не пишите логику в самих шагах: они должны только вызывать код системы.
- Следите за именами: если шаги называются по-разному, а делают одно и то же, набор быстро запутается.
Итог
Автоматизация превращает примеры в защиту от регрессий и живую документацию. Но она требует дисциплины: правильный уровень, стабильные шаги, единый язык. В пятой части, «Сквозной пример: от идеи до зелёного теста», пройдём весь цикл на одной небольшой функции.
На каком уровне вы автоматизируете проверки поведения: через UI, API или напрямую через код?