Behavior-driven development is TDD with a shared language for behavior: Given–When–Then examples that business and engineering can both read. The automation is optional but valuable; a Gherkin file nobody runs is a wiki. BDD is not “we bought Cucumber.”
The useful core
- Example mapping (or a three-amigos chat): one rule, several examples, one question you still cannot answer — that question is the work.
- Ubiquitous language for the slice, same words in the ticket, the test title, and the code. This is the overlap with DDD.
- Given–When–Then: context, action, observable outcome. No UI clicks in the When if the behavior is “funds moved.”
Given an account with balance 40 USD
When the holder transfers 20 USD to a valid payee
Then the balance is 20 USD and a TransferCompleted event is recorded
That example should fail for the same reason in an API test or a domain unit test. If it only exists as a Selenium click-path, you coupled the rule to the DOM.
sealed class Account
{
public decimal Balance { get; private set; }
public List<string> Events { get; } = new();
public static Account FromBalance(decimal balance) => new() { Balance = balance };
public void Transfer(decimal amount, string payee)
{
if (amount > Balance)
throw new InvalidOperationException("insufficient");
Balance -= amount;
Events.Add("TransferCompleted");
}
}
static void TransferOf20From40Leaves20AndRecordsTheEvent()
{
var account = Account.FromBalance(40m);
account.Transfer(20m, "payee-1");
if (account.Balance != 20m || account.Events[^1] != "TransferCompleted")
throw new Exception("the example failed");
}
When BDD pays
Ambiguous product rules, many stakeholders, acceptance that must survive a rewrite of the UI. When it does not: a one-line bugfix, a spike, a system with no human to share the language.
What breaks it
The step clicks a CSS class. That is an end-to-end script. Run the Given/When/Then above against Account.Transfer or the API.
When I click div.btn-primary
Then I should see the word success
Pitfalls
- Step soup:
When I click div.btn-primary— that is an E2E script in costume. - Duplicating the same rule in Gherkin and in a unit test that both break together.
- BDD as a QA-only afterthought once the code is frozen.