BDD-to-Code Pipeline

A contract-driven frontend production system that ensures behavioral intent is preserved through the entire development lifecycle, from specification to deployment. This pattern implements a rigorous relay model—Spec → Gherkin → Tests → Generated Code → Pipeline—where executable specifications define truth, code generation enforces structure, and automated testing arbitrates reality. Unlike traditional development models that optimize for developer speed, this system optimizes for truth, repeatability, and auditability.

Core Philosophy

This is not “BDD + tooling.” It is a behavior-first frontend factory based on the operating model:

Behavior → Structure → Verification → Enforcement

Most teams stop at “tests exist.” This pattern explicitly states that behavior defines structure, and structure is continuously enforced. That’s the difference between a demo stack and an industrial one.

Truth Claims vs Implementation

The architecture separates intent from implementation:

  • Gherkin defines truth claims about the system
  • Angular/React/Vue is merely a realization of those claims
  • Robot Framework is the arbiter of whether reality matches intent

This separation rejects:

  • UI-driven tests as primary truth
  • Unit tests as behavior proof
  • Developer interpretation as authoritative

Code Generation as Governance

Code generation is treated as structural constraint, not convenience:

  • Plop = tactical consistency (“Every component looks like this”)
  • Yellicode = architectural intent (“This system is shaped like this”)

The Four Layers

1. Specification Layer: Executable Truth (Gherkin)

Gherkin is a human-readable, plain-text language that serves as the Single Source of Truth and a living contract between stakeholders and developers.

Purpose: Bridge the gap between non-technical stakeholders (product owners) and developers.

Key Insight: Gherkin files are not “comments”—they are executable code. Because feature files are executed as specifications, they prevent “requirement drift,” ensuring documentation always reflects actual behavior.

Syntax Structure: Given, When, Then, And, But

Example:

Feature: User Login
  Scenario: Successful Login
    Given the user is on the login page
    When the user enters valid credentials
    Then the dashboard should be displayed

Relationship to OpenAPI Specification: When building RESTful APIs, an OpenAPI spec provides a wealth of details easily transformed to Gherkin. The spec defines URL paths, operations (HTTP verbs), and responses. Each (path, operation, response) combination becomes a Gherkin scenario.

2. Generation Layer: Code as Governance (PlopJS & Yellicode)

Rather than using generators for mere convenience, this system treats code generation as architectural governance.

PlopJS (Tactical Consistency)

Role: Micro-generator framework for developer experience (DX)

Purpose: Prevents copy-pasting, enforces coding standards, speeds up development

Use Case: Developer needs a new Button component. Instead of manually creating button.component.ts, button.component.html, and button.component.scss, they run npm run generate button.

Result: Instant, consistent file structure adhering to team linting rules immediately.

Templates: Uses Handlebars templates

Strategic Impact: Handles the “micro” level—boilerplate, file naming, directory structure. Makes the “right way” to build a component the only available way.

Yellicode (Strategic Architecture)

Role: Code generation for complex, modular structures based on models

Purpose: Model-driven development at higher abstraction level than Plop

Use Case: You have a data model (UML diagram or JSON definition of an API). Yellicode ingests that model and generates entire Angular modules, services, and TypeScript interfaces at once.

Result: If the API model changes, simply regenerate the code, reducing refactoring errors.

Angular Integration: Provides @yellicode/angular package to generate Angular 2+ components, services, and models

Templates: Uses TypeScript-based templates, operates on .ymn model files

Strategic Impact: Handles the “macro” level—ensuring large-scale architectural decisions are propagated programmatically, not manually. This drastically reduces technical debt.

3. Verification Layer: Behavioral Arbitration (Robot Framework)

Role: Test automation and acceptance testing

Technology: Open-source, Python-based automation framework, keyword-driven

Mechanism: Robot Framework serves as the arbiter, verifying that built reality matches original intent. It utilizes Python as “glue code” to bridge high-level Gherkin steps with low-level browser interactions or DOM assertions.

Critical Nuance: Robot Framework does not natively execute Gherkin. More precisely:

  • Gherkin feature files are parsed or mapped
  • Steps are bound to Robot keywords, often via:
    • robotframework-gherkin
    • Custom glue code
    • Preprocessing layers

Maintenance Risk: Step binding strategy becomes a maintenance risk. Poor step hygiene leads to brittle tests. The mapping layer (glue code) requires disciplined maintenance.

Browser Interaction: Likely via Selenium or Playwright libraries to interact with Angular/React DOM

Output: Generates detailed HTML reports and logs automatically, providing an auditable trail of compliance for every build

Focus: Black-box behavioral verification based on observable outcomes, not internal implementation

Example Step Definitions (using Behave/Python):

from behave import *
 
@given('a test microservice')
def create_client(context):
    # Test client setup
    pass
 
@given("umpires ['Tinker', 'Evers', 'Chance']")
def set_database(context):
    # Database setup
    pass
 
@when('request is "/umpires"')
def make_get_umpires_request(context):
    # RESTful API request
    pass
 
@then("response body includes ['Tinker', 'Evers', 'Chance']")
def assert_response(context):
    # Check the response
    pass

4. Orchestration Layer: Pipeline Enforcement (CI/CD)

Role: Automated enforcement that ensures “what is promised is what is built”

Philosophy: Pipeline enforces reality, not optimism. No manual gates. No “QA phase.” No vibes.

Causal Order:

  1. Promise (Gherkin)
  2. Shape (generation)
  3. Proof (Robot Framework)
  4. Permission to ship (CI/CD)

Pipeline Stages:

StageActionTooling
1. DefineWrite user stories in .feature filesGherkin
2. ScaffoldingGenerate boilerplate Angular codePlopJS
3. ArchitectureGenerate complex models/services from specsYellicode
4. BuildCompile the Angular applicationAngular CLI (ng build)
5. VerifyRun Gherkin scenarios against built appRobot Framework
6. ReportGenerate HTML logs of pass/fail statusRobot Framework
7. DeployIf tests pass, deployAzure DevOps / GitLab / GitHub Actions

Trigger: Code committed to Git

Result: Only code that fulfills its behavioral contract is deployed

The Relay Model: Spec to Gherkin to Code

The through-line is a relay play (borrowing baseball metaphor) from specification to working, tested code:

Spec → Gherkin → Tests → Generated Code → Pipeline

OpenAPI Specification to Gherkin Transformation

When building RESTful APIs, start with an OpenAPI specification (OAS). The nested structure:

path:
    operation:
       … (request details)
       responses:
           code: … (response details)

Each (path, operation, response) combination becomes a Gherkin scenario.

Gherkin Template:

Scenario: {operation summary} leading to {response description}
  Given {context}
  And some context tied to the response
  When {operation} on {path}
  And some reason for the response
  Then validate expected {response}

Most placeholders come directly from OAS. The exceptions are “context tied to the response” and “reason for the response”—these are implied but not stated in the spec.

Example OpenAPI Spec:

swagger: '2.0'
info:
  title: A Quick Demo
  version: '1.0'
paths:
  /umpires:
    get:
      summary: The umpires
      responses:
        200:
          description: The umpire list
          schema:
            type: object
            properties:
              status:
                type: string
                example: "OK"
              data:
                type: array
                items:
                  type: string
                example: ["Tinker", "Evers", "Chance"]

Generated Gherkin Scenario:

Scenario: Get list of Umpires
  Given a test app and client
  And a valid Authorization token is 'dizzy'
  And a test database
  And umpire names of ["Tinker", "Evers", "Chance"]
  When headers include {"x-Auth-Token": "dizzy", "Accept": "application/json"}
  And request operation is 'Get'
  And request path is '/umpires'
  Then response status is 200
  And response body is {"status": "OK", "data": ["Tinker", "Evers", "Chance"]}

Technical Gherkin: Parameterized Steps

The general shape has Given-When-Then structure, but details have changed from abstract view to specific technical details describing RESTful API implementation.

Steps are parameterized using boilerplate text followed by parameter values. The idea: create step definitions based on parsing step strings. One general Python step implementation can work with variety of parameter values.

Parameterized Step Definition:

@when('Response status is {status:int}')
def check_status(context, status):
    assert context['status'] == status

This @when definition can be reused by all Gherkin scenarios generated from the OpenAPI specification.

OpenAPI-to-Gherkin Transformation Script

A two-step transformation pipeline:

  1. OpenAPI In: Builds scenario definitions from OAS. Customizations and extensions handled when ingesting source.
  2. Gherkin Out: Writes Gherkin feature files from scenario definitions. Careful orchestration between step definitions and Gherkin text.

Internal Representation (Python dictionary):

  • Path - The path (goes into When step)
  • Operation - The operation (goes into When step)
  • Request - Details of request/parameters (populates scenario name and When steps)
  • Status - Overall final status for scenario
  • Response - Expected response example document

Top-level Function:

def make_gherkin(oaspec: Dict, file: OptFile=sys.stdout):
    common = get_common_features(oaspec)
    emit_feature_header(oaspec, file)
    for scenario in scenario_iter(oaspec):
        emit_scenario(make_scenario(common, scenario), file)

Scenario Iterator:

def scenario_iter(oaspec: Dict) -> Iterable[Dict]:
    for path in oaspec['paths']:
        for operation in oaspec['paths'][path]:
            request = oaspec['paths'][path][operation].copy()
            responses = request.pop('responses')
            for response_status in responses:
                response = responses[response_status].copy()
                yield {
                    'path': path,
                    'operation': operation,
                    'request': request,
                    'status': response_status,
                    'response': response}

Extension Properties for Error Scenarios:

OpenAPI examples typically cover only the “happy path.” For error scenarios, add extension properties:

404:
  description: Unknown umpire
  x-given: Umpires are ["Tinker"]
  x-when: request is for "Evers"

However, it’s often better to handle error scenarios in Gherkin only, rather than cluttering the OpenAPI spec.

Development Workflow

The Complete Cycle

  1. Requirement Definition: Non-technical users write features (.feature) in Gherkin to define user stories
  2. Code Generation: Developers use Plop or Yellicode to generate code structures (.ts, .html, .css) based on templates
  3. Local Testing: Developers run Robot Framework tests against the app to verify behavior defined in Gherkin
  4. Commit: Code pushed to Git
  5. CI/CD Pipeline Trigger: Automatically runs:
    • Generate: Pipeline triggers Plop/Yellicode to ensure code adheres to standards
    • Build: Angular app built (ng build)
    • Test: Robot Framework runs Gherkin scenarios to validate behavior
    • Deploy: If tests pass, app is deployed

Development Loop Example

  1. Product Owner writes a Gherkin feature: "Given a user has a premium account..."
  2. Developer uses Plop to spin up UI components and Yellicode to generate services for “premium accounts”
  3. Developer runs Robot Framework locally. Test fails (logic not written yet)
  4. Developer writes Angular logic to make test pass
  5. Code pushed. CI pipeline rebuilds app and re-runs Robot Framework suite to ensure no regressions

Living Documentation

Because Gherkin files are executed as tests, the documentation always matches the software’s actual behavior. Unlike PDF specs that get outdated the moment coding starts, Gherkin represents living documentation.

Framework Agnosticism

While this pattern currently targets Angular, the architectural spine is framework-agnostic above the generation layer:

  • Angular is replaceable
  • The pipeline is framework-agnostic above generation layer

This makes it a behavior-first frontend factory that currently targets Angular, rather than “Angular tooling.”

If you switch frontend frameworks (e.g., to React), your Gherkin tests (the business logic) remain valid; only the Robot Framework glue code needs updating.

Observable State Verification

Mature pipelines add:

  • DOM assertions
  • API contract checks
  • Visual regression (optional)

Conceptually: “Verification is based on observable outcomes, not internal implementation.”

This aligns with the black-box behavioral verification philosophy and avoids confusion when internal implementation details change.

Pattern Naming

To communicate this approach effectively, frame it as:

  • “Behavior-Locked Frontend Pipeline”
  • “Contract-Driven UI Development”
  • “Executable UX Contracts”

This helps defend against objections like “Isn’t this overkill for frontend?”

(It isn’t. It’s overkill for toy apps. For production systems requiring auditability and repeatability, it’s essential.)

Summary Table

ToolRoleFocus
GherkinSpecificationWhat the system should do (Behavior)
Robot FrameworkTestingVerifying the behavior (Automation)
PlopJSGenerationConsistency in boilerplate (Efficiency)
YellicodeGenerationComplex structure generation (Architecture)
Angular/ReactFrameworkThe technology being built
PipelineAutomationOrchestration of all steps

Complicating Factors

When building OpenAPI-to-Gherkin transformation tools, several issues arise:

  1. Naming: Organizations establish different conventions for summaries vs descriptions. Tool must reflect organizational naming conventions.

  2. Optional Features: Spec may define many optional parameters. Enumerating scenarios can be difficult to automate. Beware of combinatoric explosion: the powerset of n optional parameters is 2^n.

  3. Local Standards: Established microservice families might have standard features assumed rather than defined. May be better to handle these outside OpenAPI spec.

  4. External Dependencies: Simple microservices allow database state described with x-given extensions. Complex external dependencies may require manually-created step definitions.

  5. Unhappy Path Scenarios: Rather than clutter API description with error-processing details, better for OpenAPI-to-Gherkin tool to inject error-processing scenarios.

Umpire Metaphor: Tests as Truth

Without automated tests, there is no usable code. This parallels the three baseball umpires struggling to be fair:

  • Umpire #1: “There are balls and there are strikes, and I call them as they are.”
  • Umpire #2: “I’m only human, the very best I can do is to call them as I see them.”
  • Umpire #3: “You’re both wrong: they’re nothing until you call them.”

Umpire #3’s view parallels Acceptance Test Driven Development (ATDD). Code doesn’t work until automated tests confirm subjective impression of correct behavior. Without test results, there is no usable code.

Test cases may be the single most important artifact—potentially the only meaningful definition of correct behavior.

Comparison to Traditional Stacks

Traditional frontend stacks optimize for:

  • Speed
  • Developer happiness
  • Local reasoning

This stack optimizes for:

  • Truth
  • Repeatability
  • Auditability

This is “Ops-Core thinking applied to frontend.” That’s why this reads “serious,” not trendy.

Why This Specific Combination?

Angular + Yellicode: Powerful pairing because Angular is highly opinionated and structured. Yellicode thrives on structure, making generated code clean and “Angular-compliant.”

Gherkin + Robot Framework: Decouples test logic from test implementation. If you switch frameworks in the future, your Gherkin tests (business logic) remain valid; only Robot Framework glue code needs updating.

For deeper understanding of this pattern, see:

Next Steps

Logical progression from this pattern:

  1. Tighten this into a one-page architecture brief
  2. Turn it into a reference pipeline diagram
  3. Stress-test against real failure modes:
    • Ambiguous Gherkin
    • Generator drift
    • Flaky UI tests
    • Step binding maintenance

The spine is built. Now it’s about hardening the joints.


Source Files

This document synthesizes content from the following notebook outputs:

  1. /Users/gordie/dev/ap/library/knowledge-vault/research-lab-materials/logs/notebook outputs/BDD Frontend Production System.txt
  2. /Users/gordie/dev/ap/library/knowledge-vault/research-lab-materials/logs/notebook outputs/BDD, Generation, and Angular Pipeline.txt
  3. /Users/gordie/dev/ap/library/knowledge-vault/research-lab-materials/logs/notebook outputs/BDD.txt
  4. /Users/gordie/dev/ap/library/knowledge-vault/research-lab-materials/logs/notebook outputs/Spec to Gherkin to Code.txt
  5. /Users/gordie/dev/ap/library/knowledge-vault/research-lab-materials/logs/notebook outputs/The Behavior-First Frontend Factory.txt
  6. /Users/gordie/dev/ap/library/knowledge-vault/research-lab-materials/logs/notebook outputs/The Behavior-Locked Frontend Pipeline.txt