BDD delivers extraordinary value when done well and extraordinary waste when done poorly. The difference is the quality of your Gherkin scenarios. Well-written scenarios are business-readable, focused on one behaviour, and reusable. Poorly-written scenarios read like coded test scripts, cover too many actions, and create a maintenance burden that outweighs their documentation value. This lesson provides the rules and anti-patterns that separate effective BDD from Gherkin busywork.
BDD Golden Rules and Anti-Patterns
Apply these rules to every scenario you write, and watch for the anti-patterns during code reviews.
# BDD Golden Rules
GOLDEN_RULES = [
{
"rule": "1. Write declarative, not imperative scenarios",
"bad": "When I type 'alice' in the username field\nAnd I type 'pass' in the password field\nAnd I click the submit button",
"good": "When I log in with valid credentials",
"why": "Declarative scenarios describe WHAT happens; imperative describe HOW. "
"If the login form changes from username/password to email/SSO, "
"declarative scenarios need no update — only the step definition changes.",
},
{
"rule": "2. One behaviour per scenario",
"bad": "A 15-step scenario covering login, browse, add to cart, and checkout",
"good": "Separate scenarios: login, add to cart, checkout — each focused",
"why": "When a multi-behaviour scenario fails, you cannot tell which behaviour broke. "
"Focused scenarios give precise failure diagnostics.",
},
{
"rule": "3. Use Background for shared preconditions",
"bad": "Every scenario starts with 'Given I am logged in as standard_user'",
"good": "Background:\n Given I am logged in as 'standard_user'\n\nScenarios start with When...",
"why": "Background eliminates repetition and makes scenarios shorter and more focused.",
},
{
"rule": "4. Keep scenarios to 3-7 steps",
"bad": "A scenario with 12 Given, When, And, Then steps",
"good": "3-5 steps: Given (setup), When (action), Then (outcome)",
"why": "Long scenarios lose readability — the primary value of Gherkin.",
},
{
"rule": "5. Use Scenario Outlines for data-driven variations",
"bad": "5 identical scenarios with different usernames and expected results",
"good": "1 Scenario Outline with an Examples table containing 5 rows",
"why": "Eliminates duplication; changes to the logic require editing one template.",
},
{
"rule": "6. Write scenarios before code (shift left)",
"bad": "Writing scenarios after development to document what was built",
"good": "Three Amigos discuss and write scenarios before development starts",
"why": "Scenarios written after development are documentation, not specifications. "
"The value of BDD is aligning BEFORE code is written.",
},
]
# Anti-patterns
ANTI_PATTERNS = [
{
"name": "The UI Procedure",
"symptom": "Scenarios read like UI instructions: click, type, select, scroll",
"impact": "Scenarios break when the UI changes; stakeholders cannot read them",
"fix": "Use business-level steps: 'When I search for backpack' not 'When I type backpack into the search input and click the magnifying glass icon'",
},
{
"name": "The Swiss Army Scenario",
"symptom": "One scenario tests login, search, cart, checkout, and payment",
"impact": "Failure diagnostics are impossible; scenario is unmaintainable",
"fix": "Split into one scenario per behaviour; share setup via Background",
},
{
"name": "The Orphaned Feature File",
"symptom": "Feature files exist but are never reviewed by business stakeholders",
"impact": "BDD becomes 'Gherkin-flavoured test scripting' — no collaboration value",
"fix": "Include feature file review in sprint ceremonies; PO signs off on scenarios",
},
{
"name": "The Copy-Paste Scenario",
"symptom": "5 scenarios with identical steps except one parameter value",
"impact": "Massive duplication; changes require updating all 5 copies",
"fix": "Use Scenario Outline with Examples table",
},
{
"name": "The Technical Scenario",
"symptom": "Scenarios reference CSS selectors, API endpoints, or database tables",
"impact": "Business stakeholders cannot read or validate them",
"fix": "Keep scenarios in business language; technical details go in step definitions",
},
]
print("BDD Golden Rules:")
for rule in GOLDEN_RULES:
print(f"\n {rule['rule']}")
print(f" Why: {rule['why']}")
print("\n\nBDD Anti-Patterns:")
for ap in ANTI_PATTERNS:
print(f"\n {ap['name']}")
print(f" Symptom: {ap['symptom']}")
print(f" Fix: {ap['fix']}")
When I log in with valid credentials) survive UI redesigns because they describe business actions, not UI interactions. The step definition translates the business action into whatever UI steps are currently needed. If the login flow changes from username/password to SSO, only the step definition changes — every scenario that uses When I log in continues to work without modification.@smoke, @regression, @checkout) to categorise scenarios for selective execution. Run --tags @smoke on every PR (critical paths only, fast feedback) and --tags @regression nightly (full coverage). Tags also help organise large feature files: @wip for work-in-progress scenarios, @manual for scenarios that require manual verification, and @flaky for scenarios under investigation.Common Mistakes
Mistake 1 — Writing imperative (UI-procedure) scenarios
❌ Wrong: When I click on the search bar / And I type "laptop" / And I press Enter / And I wait for results
✅ Correct: When I search for "laptop" — one declarative step that the step definition translates to whatever UI or API calls are needed.
Mistake 2 — Adopting BDD without stakeholder participation
❌ Wrong: Testers write Gherkin scenarios in isolation; developers and product owners never see them.
✅ Correct: Three Amigos sessions produce scenarios collaboratively; PO reviews and approves feature files; scenarios serve as acceptance criteria for user stories.