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:
-
Configuration selects the executor
A concrete executor (local or remote) is chosen based on configuration.
No other layer changes. -
Steps and orchestrators express intent
Steps describe what should happen.
Orchestrators translate this into workflow operations (start, poll, fetch result). -
Services build commands
Services construct typedCommandobjects describing the intended action. -
Executors run the command
The selected executor converts the command to a runnable form (e.g., CLI string) and executes it. -
Raw output becomes a structured response
Output is captured as aCLIResponseand parsed into typed domain models. -
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¶
- Start with the Architecture Overview to understand the big picture
- Review the Layers documentation for implementation guidance
- Study the Patterns to understand workflow lifecycles and command-processing behavior
- 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.