Lesson 10: Behaviour-Driven Development

Learning Objectives

By the end of this lesson, you will be able to:

  1. Explain the BDD philosophy and how it differs from traditional test-driven development by focusing on behavior rather than implementation
  2. Apply the Given-When-Then format to write clear, unambiguous specifications that both technical and non-technical stakeholders understand
  3. Facilitate BDD collaboration through example mapping, three amigos sessions, and structured conversations that build shared understanding
  4. Create executable specifications that serve as both documentation and automated tests using BDD frameworks
  5. Integrate BDD into development workflows to bridge the gap between business requirements and technical implementation

Introduction

Behaviour-Driven Development (BDD) emerged from test-driven development with a crucial insight: the language we use to describe software shapes how we think about it and build it. While TDD focuses on testing implementation, BDD focuses on specifying behavior from a user’s perspective. This subtle shift transforms how teams collaborate, communicate, and deliver software [1].

Traditional requirements documents often suffer from ambiguity—business stakeholders and developers interpret the same requirements differently, leading to expensive misunderstandings discovered late in development. BDD addresses this by using concrete examples written in structured natural language that both business people and developers can understand and verify. These examples become executable specifications that validate the system behaves as intended [2].

The power of BDD lies in collaboration. Rather than analysts writing requirements that developers implement and testers verify in isolation, BDD brings these perspectives together early. The “three amigos”—a business representative, a developer, and a tester—collaboratively explore requirements through conversation, discovering ambiguities and edge cases before any code is written. This shared understanding dramatically reduces rework and ensures everyone works toward the same goal [3].

BDD also creates living documentation—specifications that stay synchronized with code because they’re executable tests. Unlike static documents that become outdated, BDD scenarios remain accurate because they fail when behavior changes. This provides confidence that documentation reflects reality and serves as a complete specification of system behavior [4].


Core Content

The BDD Philosophy: Behavior Over Implementation

BDD represents a fundamental shift in how we think about software development. Instead of asking “how should I test this?”, BDD asks “what behavior should this system exhibit?” [1].

Key Principles of BDD:

Outside-In Development: Start with external behavior (what users experience) and work inward to implementation. This ensures you build what users actually need.

Ubiquitous Language: Use domain language that business stakeholders understand. Avoid technical jargon in specifications.

Concrete Examples: Replace abstract requirements with specific examples that illustrate desired behavior.

Collaboration: Bring together different perspectives—business, development, testing—to build shared understanding.

Living Documentation: Specifications serve as both documentation and automated tests, staying synchronized with code.

BDD vs TDD:

While related, BDD and TDD have different focus:

TDD (Test-Driven Development):
- Focus: Implementation correctness
- Language: Technical (code-level tests)
- Audience: Developers
- Questions: "How do I test this?" "Does it work?"

Example TDD Test:
def test_discount_calculation():
    cart = ShoppingCart()
    cart.add_item(price=100)
    discount = cart.calculate_discount(customer_tier='gold')
    assert discount == 20  # 20% for gold tier

BDD (Behaviour-Driven Development):
- Focus: Business behavior
- Language: Domain terms (scenarios)
- Audience: Everyone (business, dev, test)
- Questions: "What should it do?" "Why does it matter?"

Example BDD Scenario:
Scenario: Gold tier customers receive 20% discount
  Given I am a gold tier customer
  And I have a cart with items worth $100
  When I proceed to checkout
  Then I should receive a $20 discount
  And my total should be $80

The Given-When-Then Format

Given-When-Then is the standard structure for BDD scenarios. It provides a template that’s both rigorous and readable [2].

Structure:

  • Given: Context/preconditions - the state of the world before the scenario begins
  • When: Action/event - what happens to trigger the behavior
  • Then: Outcome/postconditions - the expected result

Basic Example:

Scenario: Successful user login
  Given a user exists with email "[email protected]" and password "ValidPass123"
  And the user is on the login page
  When the user enters email "[email protected]"
  And the user enters password "ValidPass123"
  And the user clicks the "Log In" button
  Then the user should see the dashboard
  And the user should see a welcome message "Welcome back!"

Multiple Given/When/Then Clauses:

Use “And” to add additional conditions or actions:

Scenario: Calculate shipping for multiple items
  Given I am logged in as a customer
  And I have added a "Laptop" priced at $999 to my cart
  And I have added a "Mouse" priced at $29 to my cart
  And I have selected "Express Shipping"
  When I proceed to checkout
  Then I should see a subtotal of $1,028
  And I should see a shipping charge of $25
  And I should see a total of $1,053

But for Negative Conditions:

Use “But” for readability when expressing negative conditions:

Scenario: Insufficient inventory prevents order
  Given a product "Limited Edition Widget" has 2 units in stock
  When a customer attempts to order 5 units
  Then the order should be rejected
  And the customer should see an error "Insufficient inventory"
  But the product should still show 2 units in stock

Focusing on Behavior, Not Implementation:

# Bad - Too implementation-focused
Scenario: User authentication
  Given the user database contains a record with ID 123
  When the AuthService.authenticate() method is called
  Then the JWT token generation service should be invoked
  And a token with user_id=123 should be returned

# Good - Behavior-focused
Scenario: User successfully logs in
  Given I am a registered user
  When I log in with valid credentials
  Then I should have access to my account
  And I should see my personalized dashboard

Concrete Examples vs Abstract Descriptions:

# Bad - Abstract
Scenario: Products with high prices get discounts
  Given expensive products exist
  When a customer purchases them
  Then appropriate discounts should apply

# Good - Concrete
Scenario: Products over $100 receive 10% discount
  Given a product "Premium Widget" is priced at $150
  When I add it to my cart
  Then I should see a discount of $15
  And the final price should be $135

The BDD Workflow: Three Amigos and Example Mapping

BDD emphasizes collaboration through structured conversations that happen before implementation begins [3].

The Three Amigos:

Bring together three perspectives:

  1. Business/Product: Understands what needs to be built and why
  2. Development: Understands technical possibilities and constraints
  3. Testing: Understands edge cases, failure modes, and quality concerns

Three Amigos Session Structure:

1. Review the User Story (5 minutes)
   - Product owner presents the story and acceptance criteria
   - Team asks clarifying questions

2. Explore with Examples (20-30 minutes)
   - Generate concrete examples of the feature in action
   - Identify rules and edge cases
   - Use example mapping technique

3. Document Scenarios (10 minutes)
   - Convert examples into Given-When-Then scenarios
   - Identify questions that need answering
   - Assign action items

4. Review and Confirm (5 minutes)
   - Confirm shared understanding
   - Identify scenarios ready for implementation

Example Mapping:

Example mapping uses index cards to visualize the conversation:

[User Story Card - Yellow]
As a customer, I want to apply discount codes
so that I can save money on purchases

[Rule Cards - Blue]
┌─────────────────────────┐  ┌─────────────────────────┐
│ Rule: Valid codes        │  │ Rule: One code per order│
│ reduce total price       │  │                         │
└─────────────────────────┘  └─────────────────────────┘

[Example Cards - Green]
┌──────────────────────┐  ┌──────────────────────┐  ┌──────────────────────┐
│ 10% off code         │  │ Expired code fails   │  │ Invalid code fails   │
│ $100 cart → $90      │  │ Shows error message  │  │ Shows error message  │
└──────────────────────┘  └──────────────────────┘  └──────────────────────┘

[Question Cards - Red]
┌────────────────────────────────────────┐
│ Can codes be combined?                  │
│ What if code exceeds cart total?       │
└────────────────────────────────────────┘

Benefits of Example Mapping:

  • Visual: See progress and coverage at a glance
  • Focused: Keeps conversation on track
  • Collaborative: Everyone contributes equally
  • Action-oriented: Red cards become questions to resolve

Conversation Example:

Product Owner: "Users should be able to apply discount codes."

Developer: "What happens if they enter an invalid code?"

Tester: "And what if the code has expired?"

Product Owner: "Good questions. Invalid codes should show an error
               message but keep their cart. Expired codes should also
               show an error with the expiration date."

Developer: "Can users apply multiple codes?"

Product Owner: "No, only one code per order."

Tester: "What if the discount exceeds the cart total? Say they have a
         $20 code but only $15 in their cart?"

Product Owner: "Hmm, I'll need to check with management. Let's mark
               that as a red card question."

This conversation generates concrete scenarios:

Scenario: Apply valid discount code
  Given I have items totaling $100 in my cart
  When I apply discount code "SAVE10" for 10% off
  Then my cart total should be $90
  And I should see "Discount code SAVE10 applied"

Scenario: Invalid discount code shows error
  Given I have items in my cart
  When I apply discount code "INVALID"
  Then I should see an error "Invalid discount code"
  And my cart total should remain unchanged

Scenario: Expired discount code shows error
  Given discount code "EXPIRED" expired on January 1, 2025
  And today is January 15, 2025
  When I attempt to apply code "EXPIRED"
  Then I should see an error "Code expired on January 1, 2025"

Scenario: Only one discount code per order
  Given I have items totaling $100 in my cart
  And I have applied discount code "SAVE10" for 10% off
  When I attempt to apply another code "SAVE20"
  Then I should see "Only one discount code allowed per order"
  And only "SAVE10" should be applied

Implementing BDD with Frameworks

BDD scenarios become executable specifications using frameworks like Cucumber, Behave (Python), or SpecFlow (.NET) [4].

Behave (Python) Example:

Feature File (features/discount_codes.feature):

Feature: Discount Codes
  As a customer
  I want to apply discount codes
  So that I can save money on purchases

  Background:
    Given I am a registered customer
    And I have the following items in my cart:
      | product    | price |
      | Widget A   | $50   |
      | Widget B   | $50   |

  Scenario: Apply percentage discount code
    When I apply discount code "SAVE10"
    Then my subtotal should be $100
    And my discount should be $10
    And my total should be $90

  Scenario: Apply fixed amount discount code
    Given a discount code "FIXED20" for $20 off
    When I apply discount code "FIXED20"
    Then my subtotal should be $100
    And my discount should be $20
    And my total should be $80

  Scenario Outline: Invalid codes show appropriate errors
    When I apply discount code "<code>"
    Then I should see error "<error_message>"
    And my total should be $100

    Examples:
      | code      | error_message                    |
      | INVALID   | Invalid discount code            |
      | EXPIRED   | This code has expired            |
      | USED      | This code has already been used  |

Step Definitions (features/steps/discount_steps.py):

from behave import given, when, then, step
from decimal import Decimal

@given('I am a registered customer')
def step_impl(context):
    context.customer = create_test_customer()

@given('I have the following items in my cart')
def step_impl(context):
    context.cart = ShoppingCart(context.customer)
    for row in context.table:
        product_name = row['product']
        price = Decimal(row['price'].replace('$', ''))
        context.cart.add_item(product_name, price)

@given('a discount code "{code}" for ${amount:d} off')
def step_impl(context, code, amount):
    create_discount_code(
        code=code,
        type='fixed',
        amount=Decimal(amount)
    )

@when('I apply discount code "{code}"')
def step_impl(context, code):
    context.result = context.cart.apply_discount_code(code)

@then('my subtotal should be ${amount:d}')
def step_impl(context, amount):
    assert context.cart.subtotal == Decimal(amount), \
        f"Expected subtotal ${amount}, got ${context.cart.subtotal}"

@then('my discount should be ${amount:d}')
def step_impl(context, amount):
    assert context.cart.discount == Decimal(amount), \
        f"Expected discount ${amount}, got ${context.cart.discount}"

@then('my total should be ${amount:d}')
def step_impl(context, amount):
    expected = Decimal(amount)
    actual = context.cart.total
    assert actual == expected, \
        f"Expected total ${expected}, got ${actual}"

@then('I should see error "{error_message}"')
def step_impl(context, error_message):
    assert context.result['success'] is False
    assert error_message in context.result['error'], \
        f"Expected error containing '{error_message}', got '{context.result['error']}'"

Running BDD Tests:

# Run all scenarios
behave

# Run specific feature
behave features/discount_codes.feature

# Run scenarios with specific tag
behave --tags=@critical

# Generate HTML report
behave -f html -o reports/bdd_report.html

# Output:
Feature: Discount Codes # features/discount_codes.feature:1
  As a customer
  I want to apply discount codes
  So that I can save money on purchases

  Background:
    Given I am a registered customer ... passed
    And I have the following items in my cart ... passed

  Scenario: Apply percentage discount code
    When I apply discount code "SAVE10" ... passed
    Then my subtotal should be $100 ... passed
    And my discount should be $10 ... passed
    And my total should be $90 ... passed

  Scenario: Apply fixed amount discount code
    Given a discount code "FIXED20" for $20 off ... passed
    When I apply discount code "FIXED20" ... passed
    Then my subtotal should be $100 ... passed
    And my discount should be $20 ... passed
    And my total should be $80 ... passed

  Scenario Outline: Invalid codes show appropriate errors
    | code    | error_message                  |
    | INVALID | Invalid discount code          | passed
    | EXPIRED | This code has expired          | passed
    | USED    | This code has already been used| passed

3 features passed, 0 failed, 0 skipped
10 scenarios passed, 0 failed, 0 skipped
32 steps passed, 0 failed, 0 skipped

BDD as Living Documentation

BDD scenarios serve as executable documentation that stays synchronized with code [4].

Benefits of Living Documentation:

  1. Always Accurate: Fails when behavior changes, forcing updates
  2. Comprehensive: Covers all implemented behavior
  3. Understandable: Written in business language
  4. Verifiable: Can be executed to verify documentation matches reality

Documentation Structure:

features/
├── authentication/
│   ├── login.feature
│   ├── registration.feature
│   └── password_reset.feature
├── shopping/
│   ├── cart_management.feature
│   ├── checkout.feature
│   └── discount_codes.feature
└── account/
    ├── profile_management.feature
    └── order_history.feature

Each feature file documents a functional area with concrete examples.

Generated Documentation:

Many BDD tools generate human-readable documentation:

# Generate HTML documentation
behave -f html -o docs/behavior_documentation.html

# Generate Markdown documentation
behave -f markdown -o docs/features.md

Documentation Example:

# Feature: User Authentication

## As a user, I want to log in securely

### Scenario: Successful login with valid credentials
**Given** I am a registered user with email "[email protected]"
**And** my password is "ValidPass123"
**When** I enter my email and password
**And** I click "Log In"
**Then** I should be redirected to the dashboard
**And** I should see "Welcome back!"

### Scenario: Failed login with invalid password
**Given** I am a registered user
**When** I enter my email with an incorrect password
**Then** I should see error "Invalid email or password"
**And** I should remain on the login page
**And** I should not be logged in

This documentation is generated from executable scenarios, ensuring it’s always accurate.


Common Pitfalls

Pitfall 1: Writing Implementation-Focused Scenarios

Scenarios that describe implementation details rather than behavior break when refactoring even though behavior hasn’t changed.

# Bad - Implementation details
Scenario: User login
  When the AuthController.login() method receives credentials
  And the PasswordHasher validates the bcrypt hash
  Then a JWT token should be generated with HS256 algorithm

# Good - Behavior focus
Scenario: User logs in successfully
  Given I am a registered user
  When I log in with valid credentials
  Then I should have access to my account

Best Practice: Write scenarios from a user’s perspective. Avoid mentioning classes, methods, databases, or technical implementation [1].

Pitfall 2: Insufficient Collaboration

Developers writing scenarios alone without business input defeats BDD’s purpose of shared understanding.

Best Practice: Require three amigos sessions for all new features. Schedule them early, before implementation begins. Product owner must approve scenarios [3].

Pitfall 3: Scenarios as Acceptance Tests Only

Using BDD only for high-level acceptance testing misses its value for guiding development and creating documentation.

Best Practice: Write scenarios at multiple levels—feature-level scenarios for acceptance, component-level scenarios for complex logic. Use BDD throughout development, not just at the end [4].

Pitfall 4: Vague or Abstract Scenarios

Abstract scenarios without concrete examples are open to interpretation, recreating the ambiguity BDD aims to eliminate.

Best Practice: Use specific, concrete examples with actual values. If the scenario seems vague, it probably needs more specific examples from the three amigos session [2].


Summary

Behaviour-Driven Development bridges the gap between business requirements and technical implementation through collaboration and concrete examples expressed in structured natural language.

The BDD philosophy focuses on behavior rather than implementation, using domain language that all stakeholders understand. Unlike TDD which tests implementation, BDD specifies behavior from the user’s perspective, creating shared understanding across business, development, and testing roles.

Given-When-Then format provides a rigorous yet readable structure for scenarios. Given establishes context, When describes the action, and Then specifies the outcome. This format forces clarity and eliminates ambiguity while remaining accessible to non-technical stakeholders.

Three amigos collaboration brings together business, development, and testing perspectives early in the development process. Through structured conversations and example mapping, teams discover edge cases, resolve ambiguities, and build shared understanding before writing code. This collaboration dramatically reduces rework and misunderstandings.

Executable specifications created with BDD frameworks like Behave or Cucumber serve dual purposes: automated tests that verify behavior and living documentation that stays synchronized with code. When scenarios fail, they highlight discrepancies between documented and actual behavior.

Living documentation generated from BDD scenarios provides comprehensive, accurate documentation that’s always up-to-date. Unlike static documents that become outdated, BDD scenarios must be maintained alongside code, ensuring documentation reflects reality.

BDD transforms development from implementation-focused activities to conversation-focused collaboration. The scenarios created aren’t just tests—they’re the shared language through which teams understand what they’re building, why it matters, and how to verify success.


Practice Quiz

Question 1: A developer writes this BDD scenario. What’s wrong with it?

Scenario: Process order
  Given the OrderService has a database connection
  When the create_order() method is called with valid OrderDTO
  Then the OrderRepository.save() should be invoked
  And the NotificationService.sendEmail() should be called
  And the method should return an Order object

Answer: This scenario violates BDD principles by focusing on implementation details rather than user behavior:

Problems:

  1. Mentions technical components (OrderService, OrderRepository)
  2. Specifies method names (create_order(), save(), sendEmail())
  3. References implementation concepts (DTO, database connection)
  4. Tests how the system works internally, not what behavior users observe

Fixed version:

Scenario: Customer successfully places an order
  Given I am a logged-in customer
  And I have items in my shopping cart
  When I submit my order with shipping address
  Then I should see an order confirmation
  And I should receive an order confirmation email
  And my order should appear in my order history

This focuses on observable behavior from the user’s perspective, not implementation details. It describes what happens, not how it happens [1][2].

Question 2: Your team holds a three amigos session for a new feature: “Users should be able to filter products.” The developer immediately starts writing technical scenarios about database queries. What’s going wrong, and how should the session proceed?

Answer: The developer is jumping to implementation before understanding the behavior. Three amigos sessions should focus on what before how.

Better approach:

Facilitator (Tester): "Let's start with examples. What filtering do users need?"

Product Owner: "They should filter by category, price range, and brand."

Developer: "For price, do they enter exact amounts or select ranges?"

Product Owner: "Good question. Probably predefined ranges like 'Under $50', '$50-$100', etc."

Tester: "What if they select multiple filters? Like 'Electronics' category AND '$50-$100'?"

Product Owner: "Yes, filters should combine—show products matching all selected filters."

Developer: "So if no products match, what happens?"

Product Owner: "Show 'No products found' with option to clear filters."

Tester: "And filters should be clearable individually or all at once?"

Product Owner: "Right, individual 'X' buttons and a 'Clear All' button."

Resulting scenarios:

Scenario: Filter products by single category
  Given there are products in multiple categories
  When I filter by "Electronics" category
  Then I should see only electronics products

Scenario: Filter products by multiple criteria
  Given there are products across categories and prices
  When I filter by "Electronics" category
  And I filter by price range "$50-$100"
  Then I should see only electronics priced between $50 and $100

Scenario: No products match filter criteria
  Given no products match my selected filters
  Then I should see "No products found"
  And I should see an option to clear filters

Key principle: Focus on user behavior and concrete examples, not database queries or technical implementation [3].

Question 3: Your BDD scenarios all pass, but users report the feature doesn’t work correctly. What might explain this, and what BDD practices would prevent it?

Answer: Several possible causes:

1. Scenarios test wrong behavior:

# Scenario tests what was built, not what was needed
Scenario: User can add items
  Given I am on the product page
  When I click "Add to Cart"
  Then the item count increases

# But users actually need:
Scenario: User can purchase items
  Given I have items in my cart
  When I complete checkout with valid payment
  Then I should receive my order
  And my payment should be processed

Prevention: Ensure product owner participates in three amigos and approves scenarios before implementation [3].

2. Insufficient coverage of edge cases:

# Only tested happy path
Scenario: Add item to cart
  When I add an item
  Then it appears in my cart

# Missing critical scenarios:
Scenario: Add out-of-stock item
Scenario: Add item exceeding purchase limit
Scenario: Add item to cart from different currency region

Prevention: Tester’s role in three amigos is identifying edge cases and failure modes. Use example mapping to visualize coverage [3].

3. Scenarios too high-level:

# Too vague
Scenario: Checkout works
  When I checkout
  Then I should complete my order

# Should be specific:
Scenario: Checkout with credit card
  Given I have items totaling $100
  When I enter valid credit card details
  And I confirm payment
  Then I should see "Order confirmed"
  And my card should be charged $100
  And I should receive confirmation email

Prevention: Use concrete examples with specific values. Abstract scenarios hide gaps [2].

Key BDD practice: Scenarios should specify acceptance criteria that, if all pass, mean the feature is complete and correct. If scenarios pass but feature doesn’t work, scenarios were incomplete or tested wrong behavior [4].

Question 4: Your codebase has 200 BDD scenarios that take 15 minutes to run. Developers stop running them before commits. How should you address this?

Answer: The scenario suite is too slow and likely improperly structured. BDD scenarios should follow a pyramid similar to unit/integration tests.

Solutions:

1. Separate levels of scenarios:

@unit           # Fast, isolated scenarios (run constantly)
@integration    # Moderate speed, with dependencies (run before push)
@e2e           # Slow, full system (run in CI only)

2. Tag scenarios appropriately:

@unit @critical
Scenario: Calculate discount correctly
  Given cart total is $100
  When 10% discount is applied
  Then total should be $90

@integration
Scenario: Complete checkout process
  Given logged-in user with items in cart
  When user completes checkout
  Then order is created and confirmation sent

@e2e @slow
Scenario: Full user journey from registration to purchase
  [Long end-to-end scenario]

3. Run appropriate scenarios:

# During development (seconds)
behave --tags=@unit

# Before commit (1-2 minutes)
behave --tags=@unit --tags=@integration

# In CI (full suite)
behave

4. Optimize slow scenarios:

  • Use test doubles for external services in lower-level scenarios
  • Parallel execution: behave --processes 4
  • Background data: Set up test data once, not per scenario

Target: Unit-level scenarios in seconds, integration scenarios in 1-2 minutes, full suite in CI [4].

Question 5: Your team debates whether BDD scenarios should test internal business logic or only user-facing features. What’s the correct approach?

Answer: Both, but at different levels with different audiences.

Feature-level scenarios (user-facing):

Feature: Apply discount codes
  As a customer
  I want to apply discount codes
  So that I can save money

  Scenario: Apply valid discount code
    Given I have a cart total of $100
    When I apply discount code "SAVE10"
    Then my total should be $90

Audience: Business stakeholders, product owners Focus: User-visible behavior Language: Domain terms users understand

Component-level scenarios (business logic):

Feature: Discount calculation engine
  Covers complex discount rules and edge cases

  Scenario: Percentage discount on pre-tax amount
    Given a cart with pre-tax total of $100
    And tax rate of 10%
    When a 10% discount code is applied
    Then discount should be $10 (10% of $100, not $110)
    And tax should be $9 (10% of $90)
    And final total should be $99

  Scenario: Discount capped at maximum amount
    Given a cart with total of $1000
    When a 50% discount code with $400 cap is applied
    Then discount should be $400, not $500
    And final total should be $600

Audience: Developers, testers Focus: Complex business rules Language: Precise business terms

Guideline:

  • Write feature-level scenarios for all user-facing functionality
  • Write component-level scenarios for complex business logic, algorithms, or calculation rules
  • Keep them in separate feature files organized by area
  • Product owners review feature-level, developers own component-level [1][4]

References

[1] North, D. (2006). “Introducing BDD.” URL: https://dannorth.net/introducing-bdd/, Quote: “BDD is about implementing an application by describing its behavior from the perspective of its stakeholders. It focuses on obtaining a clear understanding of desired software behavior through discussion with stakeholders, using concrete examples to build shared understanding.”

[2] Adzic, G. (2011). Specification by Example: How Successful Teams Deliver the Right Software. Manning Publications. URL: https://www.manning.com/books/specification-by-example, Quote: “Key examples illustrate business rules and demonstrate expected system behavior in concrete terms that both technical and non-technical stakeholders can understand. Using concrete examples instead of abstract requirements eliminates ambiguity and provides a shared language for discussing software.”

[3] Wynne, M., & Hellesoy, A. (2017). The Cucumber Book: Behaviour-Driven Development for Testers and Developers (2nd Edition). Pragmatic Bookshelf. URL: https://pragprog.com/titles/hwcuc2/the-cucumber-book-second-edition/, Quote: “The Three Amigos meeting brings together business, development, and testing perspectives to explore requirements through conversation before implementation begins. Through example mapping and structured discussion, the team discovers edge cases, resolves ambiguities, and builds shared understanding that dramatically reduces rework.”

[4] Smart, J. F. (2014). BDD in Action: Behavior-Driven Development for the Whole Software Lifecycle. Manning Publications. URL: https://www.manning.com/books/bdd-in-action, Quote: “BDD scenarios serve as executable specifications—they’re both automated tests that verify behavior and living documentation that stays synchronized with code. When scenarios fail, they highlight discrepancies between documented and actual behavior. This living documentation provides comprehensive, accurate system documentation that’s always up-to-date.”