Skip to content

BDD Diagram

BDD Framework Design

A practical, technology‑neutral blueprint for designing maintainable and extensible BDD automation frameworks.
This approach is suitable for cloud‑native systems, serverless workflows, distributed compute engines, API‑driven automation, and high‑security or restricted environments where direct access to runtime infrastructure is limited.

The architecture prioritises clear separation of test intent, workflow orchestration, command execution, and output interpretation. It generalises easily across multiple execution models—local, remote, containerised, serverless, or cluster‑based—without requiring changes to BDD steps or test logic.

Overview

This documentation introduces a layered architecture for BDD automation that cleanly separates test intent, orchestration flow, command execution, and output interpretation. The same architectural principles apply whether workflows run on a serverless engine, a distributed compute framework such as Spark, a container orchestration platform, or a remote API. Tests remain fully portable because execution concerns are delegated to interchangeable Executors. The rest of the framework (steps, orchestrators, services) stays unchanged while execution is swapped via configuration. Parsing is optional: if output is already structured (e.g., JSON), response models can hydrate directly without a parser.

Architecture Philosophy

The framework follows a strict separation of concerns: BDD steps express intent, orchestrators manage lifecycles, services coordinate execution, and executors abstract the underlying systems.

Quick Start

The framework is organized into seven conceptual layers, each with specific responsibilities:

graph TD
  Step[BDD Step Layer] --> Orch[Orchestrator]
  Orch --> Svc[Service Layer]
  Svc --> Cmd[Command Layer]
  Cmd --> Exec[Executor Layer]

  classDef layer fill:#e3f2fd,stroke:#90caf9,stroke-width:1px,color:#000,font-size:12px;
  class Step,Orch,Svc,Cmd,Exec layer;

Execution Flow and Configuration

At the core of this architecture is a simple and predictable lifecycle:

  1. Configuration selects the executor
    A concrete executor (local or remote) is chosen based on configuration.
    No other layer changes.

  2. Steps and orchestrators express intent
    Steps describe what should happen.
    Orchestrators translate this into workflow operations (start, poll, fetch result).

  3. Services build commands
    Services construct typed Command objects describing the intended action.

  4. Executors run the command
    The selected executor converts the command to a runnable form (e.g., CLI string) and executes it.

  5. Raw output becomes a structured response
    Output is captured as a CLIResponse and parsed into typed domain models.

  6. Orchestrators evaluate results
    Parsed results inform whether the workflow continues, succeeds, or fails.

This keeps test intent stable while allowing full flexibility in how commands run.

Key Benefits

  • Maintainable: Clear separation between test intent, orchestration, and execution
  • Extensible: Plug-and-play executors without rewriting services
  • Traceable: Declarative commands enable audit trails and replay capabilities
  • Consistent: Typed responses ensure predictable structure across workflows.
  • Flexible: Execution mode can switch between local runtime and remote invocation without modifying tests
  • Multi‑domain applicability: Suitable for batch workloads, serverless orchestrations, API‑based workflows, distributed compute pipelines, and secure runtime environments.

Technology Foundations

This architecture is designed to work naturally with:

  • Pydantic (optional) — for modelling commands and structured responses using typed, declarative models.
  • pytest / pytest-bdd — providing step-based testing, fixtures, and clean separation of concerns.
  • pytest-xdist — enabling parallel execution for scalable end-to-end testing.

These tools are not required but align well with the layered patterns described in this documentation.

What Problems This Solves

  • Fragile automation tightly coupled to specific infrastructure (local machines, CI workers, cloud environments, or secured clusters)
  • Unstructured, inconsistent handling of CLI or API output across different workflow systems
  • Lack of a structured lifecycle for long‑running workflows
  • Difficulty scaling reusable BDD steps across teams
  • Orchestration logic leaking into test files

Core Patterns

The framework implements several key patterns:

Polling Lifecycle

sequenceDiagram
  participant Test
  participant Orch
  participant Svc
  participant Exec
  participant Target
  Test->>Orch: start_workflow()
  Orch->>Svc: submit()
  Svc->>Exec: run(start_cmd)
  Exec->>Target: execute
  loop until complete
    Orch->>Svc: check_status()
    Svc->>Exec: run(status_cmd)
    Exec->>Target: poll
  end
  Orch->>Test: result

Command Processing

graph LR
  C[Command] --> E[Executor]
  E --> O[Raw Output]

  %% Optional parsing step (only needed for text or mixed output)
  O -->|optional| P[Parser]

  %% Unified, typed response wrapper
  P --> R[CLIResponse]
  O --> R[CLIResponse]

  %% Final domain object (e.g., WorkflowResponse)
  R --> D[Typed Domain Response]

  classDef node fill:#e3f2fd,stroke:#90caf9,stroke-width:1px,color:#000,font-size:12px;
  class C,E,O,P,R,D node;

In practice, a Command is usually a typed model with a to_cli() method, the executor is selected via configuration, and the response path flows through a CLIResponse object before being turned into a final domain model. This keeps the command → execution → parsing pipeline explicit, testable, and easy to extend. Parsing is used only when normalisation is required; structured outputs bypass parsing entirely.

Why Pydantic Works Well Here

Pydantic (v1 or v2) provides:

  • Validation and normalisation of command inputs and outputs
  • Clear, typed models for workflow requests and responses
  • Easier debugging and traceability through structured data

Pydantic is optional, but strongly complements the typed command and response models used throughout this blueprint.

Documentation Navigation

  • Architecture Overview: Detailed explanation of the layered approach
  • Layers: Deep dive into each conceptual layer
  • Patterns: Core behavioral patterns and interaction flows
  • Glossary: Definitions of key terms and concepts
  • Extending & CI/CD: How the decoupled framework is packaged, versioned, and consumed by test repositories

Next Steps

  1. Start with the Architecture Overview to understand the big picture
  2. Review the Layers documentation for implementation guidance
  3. Study the Patterns to understand workflow lifecycles and command-processing behavior
  4. Refer to the Glossary for terminology clarification

Documentation Scope

This repository contains documentation only. All examples are conceptual and vendor-neutral. No production code or specific infrastructure details are included.