When Code Speaks the Language of Business: An Introduction to BDD
Imagine this situation: you've written a perfect payment module from a code perspective. All methods work, exceptions are handled, unit test coverage is 99%. You're about to pop the champagne, but the manager comes in and says, "Why are we charging money before the order is confirmed?" And you realize — the bug isn't in the code, but in the understanding of the task.
Sound familiar? This is exactly the kind of case where BDD (Behaviour-Driven Development) comes in — development driven by behavior. It's not just another methodology, but a bridge between "I want it to work" and "how to implement it in PHP." If you're tired of rewriting logic after every requirement clarification, this article is for you.
In this material, we'll break down how to implement BDD in PHP using the Behat framework, write real tests, and understand why it makes code cleaner and communication more transparent.
What is BDD and How is it Different from TDD?
Many people confuse Behaviour-Driven Development with regular TDD (Test-Driven Development). And indeed, they look similar on the surface: in both cases, tests are written first. But the difference is in the focus.
- TDD is about "how to check that a function returns the correct number." Tests are written in the programmer's language: assert, equals, mock.
- BDD is about "how the system behaves in a specific business situation." Scenarios are written in natural, almost human language.
The key idea of BDD in PHP is to use a unified language for communication. Developers, testers, and managers all read the same scenario. And if it says "the user adds a product to the cart without logging in," everyone understands it the same way.
Tooling: Behat and Gherkin
In the PHP world, the main tool for BDD is Behat. It's a framework that parses scenarios written in the Gherkin language and turns them into executable tests. Gherkin is simple English (or Russian) with keywords: Feature, Scenario, Given, When, Then.
Let's install Behat into your PHP project:
composer require --dev behat/behat behat/mink-extension behat/mink-goutte-driverAfter installation, initialize the project:
vendor/bin/behat --initThe structure will look like this:
features/ bootstrap/ FeatureContext.php your_feature.featurebehat.ymlWriting Your First BDD Scenario in PHP
Let's say we have an online store. The business requirement is: "A registered user can add a product to the cart and see the total amount." Create the file features/cart.feature:
Feature: Shopping Cart As a registered user I want to add products to the cart So that I can see the total cost
Scenario: Adding a single product Given I log in to the site as user "ivan@example.com" And the catalog page has a product "Laptop" for 50000 rubles When I click "Add to cart" for the product "Laptop" Then I see the message "Product added" And the total cart amount is 50000 rublesNotice: any manager can read this scenario without knowing PHP. But for Behat, it's an executable test.
Implementing Step Definitions
Now we need to "teach" Behat to understand these steps. Open features/bootstrap/FeatureContext.php:
<?php
use Behat\\Behat\\Context\\Context;use Behat\\Gherkin\\Node\\PyStringNode;use Behat\\Gherkin\\Node\\TableNode;
class FeatureContext implements Context{ private $currentUser; private $cart = []; private $products = [];
/** * @Given I log in to the site as