Behavior-Driven Development (BDD)

Origins

Behavior-Driven Development was coined by Dan North around 2003 as a refinement of Test-Driven Development. North's observation was that newcomers to TDD got stuck on what to test — the word "test" pointed at verification, when the actual practice was about specifying behavior. He proposed reframing the discipline around behavior: what should the system do, expressed in language a non-engineer could read.

The reframing produced the Given-When-Then format that became BDD's calling card, and a family of tools (Cucumber, SpecFlow, Behat, JBehave) that let those scenarios be executed as automated tests. Gojko Adzic's Specification by Example1 and Liz Keogh's work formalized the conversational discipline around the format.

The Given-When-Then Format

A BDD scenario has three clauses:

  • Given: the starting context. What is true before the behavior happens.
  • When: the action or event that triggers the behavior.
  • Then: the observable outcome. What should be true after.

Example:

Scenario: Returning customer applies a coupon
Given I have an item in my cart priced $50
And a coupon code "SAVE10" exists that gives 10% off
When I apply the coupon at checkout
Then the order total should be $45

The scenario reads as English. A product manager can write it; a developer can implement against it; a tester can verify it; an automated tool can execute it as a test.

BDD Is Three Things

BDD as commonly practiced has three layers, and the distinction matters:

1. A conversation discipline

The most important layer. Before writing scenarios, the team has a structured conversation about what the system should do. Example Mapping is a common format. The conversation produces shared understanding; the scenarios capture it.

2. A specification format

Given-When-Then scenarios that capture what the conversation produced. These can serve as acceptance criteria, as living documentation, and as a contract between business and engineering.

3. An automation layer

Tools (Cucumber, SpecFlow, etc.) that execute the scenarios as automated tests. This is the most visible BDD artifact but the least important — the conversation and the scenarios are valuable even without automation.

Teams that adopt only the automation layer get the worst of BDD: complex test infrastructure with little of the shared-understanding value. Teams that adopt the conversation and specification layers get most of the benefit even if they never automate the scenarios.

What Makes a Good Scenario

  • Business language, not technical: "the order total" not "the total field of the OrderEntity"; "the customer is logged in" not "session.user_id is set."
  • Specific values: "$50" not "an amount"; "SAVE10" not "a valid coupon." Concrete examples avoid ambiguity.
  • One behavior per scenario: a scenario that tests three things is hard to read and hard to maintain.
  • Independent: the scenario should make sense on its own without context from other scenarios.
  • Declarative, not imperative: "I have a $50 item in my cart" not "I click 'add to cart' on item ID 12345 and wait for the page to load."

BDD vs. TDD

The relationship is layered, not opposed:

  • TDD drives unit-level design. The tests describe what individual classes or functions should do.
  • BDD drives feature-level design. The scenarios describe what the system as a whole should do.

A team practicing both has BDD scenarios as the outer specification of features and TDD unit tests as the inner driver of code design. Each scenario gets broken down into many unit tests; each unit test serves the scenario above it.

Common Pitfalls

  • BDD as automation, not conversation: the team adopts Cucumber but skips the conversation discipline. The scenarios become technical tests dressed in English, with all the maintenance cost and none of the shared-understanding benefit.
  • Imperative Given-When-Then: scenarios that describe UI clicks step by step rather than the underlying behavior. The scenarios break every time the UI changes; the maintenance burden becomes unmanageable.
  • Too many scenarios: a feature with 50 scenarios is harder to read than the code it's testing. Cover the important paths and edge cases; not every possible variation.
  • Scenarios as test scripts: written by QA after the feature is built, locked in as regression tests, never revisited. The format works best when written before the feature and revised as understanding shifts.
  • Wrong audience: scenarios that no business stakeholder ever actually reads. BDD's promise is shared understanding; if only the engineers see the scenarios, the format hasn't earned its overhead.

Coaching Tips

Start with the Conversation

Don't lead with Cucumber. Run Example Mapping sessions first. The conversation discipline is where BDD's value lives.

Push for Business Language

Scenarios that read like UI scripts have failed at their job. Reframe imperative steps into declarative behavior.

Confirm the Audience

If business stakeholders never read the scenarios, BDD's overhead isn't paying off. Either bring them in or simplify.

Use Concrete Examples

"A valid coupon" is vague. "SAVE10 giving 10% off" is concrete. Specifics make scenarios useful; abstractions defeat the format.

Don't Test Everything

BDD's not a coverage tool. Cover the important paths and edge cases; let TDD unit tests cover the combinatorics.

Pair BDD with TDD

Scenarios specify features; unit tests drive code design. Each scenario decomposes into multiple unit tests. Together they cover both layers.

Summary

BDD's promise is genuine but easily misunderstood. The promise is not better tests — it is shared understanding between business and engineering, captured in a form precise enough to execute. Teams that adopt the conversation and specification disciplines often get more value from BDD than teams that adopt the tooling alone.

The format isn't right for every team or every codebase. Where business stakeholders are absent or uninterested in scenarios, the conversation layer dies and the format becomes overhead. Where the team's complexity lives in algorithms or infrastructure rather than user-facing behavior, BDD's strengths don't apply. But where features are the unit of work and business and engineering need to communicate clearly about them, BDD is one of the cleanest ways to do it.

Back to Technical Practices