Est.

BDD Testing With Cucumber in Agentic CI Pipelines

Explicit Gherkin contracts let agents plan changes and verify behavior without human intervention.

· 9 min read
Cover illustration for “BDD Testing With Cucumber in Agentic CI Pipelines”
Behavior-Driven Development · October 29, 2026 · 9 min read · 1,980 words

BDD testing with Cucumber in agentic CI pipelines turns Gherkin scenarios into executable contracts that agents use to plan changes, verify behavior, and self-correct. The quality of those contracts is the strongest lever for pipeline reliability. An agent can act without human intervention at every step only when the specification makes the intended behavior explicit and the execution results make failures actionable.

Why Gherkin scenarios become the agent's ground truth in agentic CI

Traditional CI tests code written by a human who knows how it should behave, including context that was never written down in the repository. An agent has no such implicit intent. It needs an executable contract before making changes as well as regression checks afterward. Deepak Babu Piskala’s technical report, Spec-Driven Development: From Code to Contract in the Age of AI Coding Assistants, describes the alternative as producing “plausible-looking code that makes dozens of unstated assumptions — many of them wrong”.

In most pipelines, Gherkin is the artifact that can supply that contract in both readable and executable form. Cucumber links its plain-language scenarios to step definitions that turn what should happen into automated checks. The specification becomes the source of truth. Code is then a secondary artifact whose correctness is judged against the declared behavior, rather than the basis from which that behavior is inferred.

What Cucumber's three-layer architecture actually gives an agent to work with

Cucumber separates feature files, step definitions, and the test runner. Feature files state what should happen in plain-language .feature files written in Gherkin, which an agent can parse without running application code. Step definitions map that language to executable methods, using annotations such as @Given, @When, and @Then. The runner connects the two layers, launches execution, and collects results.

For example, a Given step declares a precondition, a When step describes an action, and a Then step states the expected outcome. The step definition is where each declaration becomes machine action. In a Java setup, JUnit or TestNG provides the runner entry point. Cucumber’s language flexibility also supports step-definition work in Ruby, Python, JavaScript, and other runtimes.

These layers establish the agent’s read path. It parses a feature for intent, locates or generates matching step definitions, invokes the runner, and reads structured pass, fail, or pending results. That separation lets the agent distinguish what the system should do from how the test exercises it.

How the workflow inverts when agents draft Gherkin instead of developers

Traditional BDD often starts with developers writing scenarios based on the implementation, while business analysts may never work with the result. Scenarios then drift toward descriptions of code or UI operations. Agent-authored Gherkin reverses that information flow. The agent drafts scenarios from requirements, and a business analyst or platform engineer refines them before they become executable contracts in the pipeline.

That inversion makes review of the specification a reliability control. An agent that lacks some of the context can write vague Then steps, UI-heavy scripts, scenarios that cover several behaviors, or examples full of placeholders. These are missing-context problems. The agent needs explicit rules for Gherkin just as it needs linting rules for code.

The SDD report calls “spec-anchored development” the “sweet spot for most production systems”. In that model, the specification stays with the code and synchronization is enforced, without requiring all code to be generated from specifications. People therefore still need to refine the specification even when agents run routine checks and make fixes on their own.

What makes a Gherkin scenario actually consumable by an agent

For agent consumption, the practical rule is one behavior per scenario. A scenario combining separate acceptance criteria gives the agent an ambiguous target when it fails. The correct alternative is to split those behaviors so that each failure identifies a specific gap. This is fault isolation at the specification layer.

Then steps also need observable outcomes. “The user is happy” gives an agent nothing it can assert programmatically, while a response status, database state, or emitted event provides a verifiable result. Likewise, a Scenario Outline filled with placeholder examples gives the agent little to work with when it reasons about edge cases. Data that reflects real cases gives the agent cases to run and build on, while Data Tables give it structured input for complex preconditions.

“Given the user clicks the login button and enters a password” binds the precondition to an interaction sequence. “Given the user has an active account” declares the state the behavior requires. The latter preserves intent when the UI changes and keeps acceptance testing focused on integration and E2E behavior.

Where Cucumber scenarios slot into an agentic CI pipeline as execution gates

Cucumber belongs after fast unit tests in the acceptance-test layer, where integration and E2E scenarios check behavior that tests run in isolation cannot confirm. It is not a unit-test replacement. Running Cucumber checks on every push detects behavioral regressions while the agent is still working on the change, rather than postponing that feedback until a release branch.

A failed gate gives the agent a named feature, scenario, failing step, and stack trace. Those coordinates support a direct correction loop. The agent reads the report, locates the relevant step definition, revises the implementation, and reruns the check. Gate placement therefore determines how soon the agent receives evidence that its change violates the contract.

The same evidence helps the merge queue decide what to do when agents create pull requests at machine speed. Behavioral failures must be fixed before changes move through the queue. Cucumber results serve as a serialization signal that helps decide which changes can go ahead, as well as adding a red or green indicator to a pull request.

How the agent uses failing scenarios to plan changes, not just detect them

A failing Then step describes the gap between the current implementation and the required outcome. That gap can become a scoped change request. The agent reads the declared result, identifies what the implementation does differently, and plans a change limited to satisfying the contract. It then reruns the scenario to test that plan.

Scenario granularity directly constrains the quality of this reasoning. When a scenario conflates behaviors, the agent cannot isolate the gap cleanly and may change more than necessary. A vague instruction to “fix the CI failure” is weaker still, because it invites pattern completion. Making one test green does not establish correctness for behavior the suite never specified.

In multi-agent pipelines, a reviewing agent can use the same structured results to assess whether the coding agent’s fix satisfies the scenario without breaking others. Production failures extend this planning loop. A production exception or deploy failure should map to an existing scenario or trigger a new one, turning the operational signal into an executable requirement for the next iteration.

Structuring step definitions so agents can generate and maintain them reliably

Step definitions are the semantic seam between readable intent and executable checks. A mistake here can produce a green scenario that validates the wrong behavior. Linting and type-checking do not establish that the implementation of a step matches its language. Agent maintenance therefore requires predictable scope at this layer.

The practical rule is one step definition per intent. Sharing genuinely stateless, stable steps reduces duplication, but sharing changing business logic creates hidden coupling between scenarios. An agent modifying that logic to satisfy one scenario can break others that reuse it. Isolating those steps makes the likely reach of a change easier to determine.

Hooks such as @Before and @After provide the place for state setup and teardown. Keeping lifecycle work out of step definitions lets agents modify a step without also altering how test state is prepared or cleaned up. Review should focus especially on shared-state risks and whether assertions implement the declared outcome, because those errors can survive ordinary code checks.

Tagging and reporting as the interface between Cucumber and the agent's decision loop

Labels such as @smoke, @critical-path, and @regression let it select checks appropriate to the pipeline stage. Running a few chosen critical-path scenarios in fast pre-merge checks gives early feedback without the need to run the full acceptance suite for each first decision.

Reports provide the evidence after execution finishes. Cucumber supports HTML, JSON, and JUnit XML output, with JSON exposing the feature, scenario, failing step, error message, and stack trace for programmatic consumption. A pending step is a different signal from a failure. It identifies specified behavior that has not yet been implemented and should enter the agent’s work queue.

When checks run in parallel, the agent must gather results from all runs before deciding to merge or hold so that it has the full picture. Unstable scenarios also need distinct treatment. An explicit @flaky tag is a practical first step toward quarantining alternating pass/fail signals so that noise does not trigger unnecessary code changes.

Choosing between Cucumber and other BDD frameworks for an agentic pipeline

Cucumber is a strong default, but stack fit can justify an alternative. Friction in a framework adds up as agents write and maintain step definitions again and again. For Java/Spring Boot teams, Cucumber-JVM 7+ offers JUnit 5 and TestNG support, a large community, and IDE integration. Reqnroll, the community-backed SpecFlow successor, fits.NET 8 and Visual Studio teams, although migration from SpecFlow is not necessarily effortless.

Python teams have two relevant choices. Behave is standalone and simpler when pytest is not already in place, while pytest-bdd reuses existing pytest fixtures. Both retain Gherkin as the agent-readable contract. Gauge instead uses markdown specifications and has native parallel execution, with a different specification format that gives up Gherkin’s tighter structure.

Karate combines BDD with API and contract testing without a separate step-definition layer, making it appropriate when REST/GraphQL testing dominates. JBehave has a place in regulated Java environments where compliance rules require its audit trail. Hybrid setups are also legitimate. Karate can cover API-layer BDD while Cucumber handles UI/E2E acceptance, as long as the pipeline sends failures to the right layer.

How composable pipeline infrastructure handles Cucumber's output at scale

At machine-speed pull request volume, the constraint shifts toward which agent receives a result and whether it acts on the right signal. Maintenance changes involving dependencies, configuration, and test scaffolding compete with feature work. Without queue management, even precise Cucumber failures can accumulate as unacted-on evidence.

An agent-operated merge queue addresses that routing problem by reading results, reconciling parallel changes, and surfacing failures that require human judgment. Humans need not interpret every routine run. The distinction is between a pipeline that produces test evidence and one that delivers it to the agent responsible for the next decision.

Production signals need the same direct path into planning rather than remaining in a dashboard until someone opens a ticket. These capabilities do not require replacing the BDD framework. A team running Cucumber on Java can add agent-operated merge queues and transcript analysis over its existing test infrastructure, keeping the behavioral contract separate from the machinery that coordinates work.

Practical steps for making an existing Cucumber suite agent-ready

For platform engineers, migration can proceed as a set of independent checks this sprint. Start by auditing scenarios that combine behaviors and splitting them into isolated acceptance criteria. Replace imperative UI sequences with declarative behavioral steps. These changes give the agent a clearer failure signal before it takes on more maintenance on its own.

Apply @smoke to critical-path scenarios and @flaky to known unstable ones, and emit JSON reports with HTML. Configure CI to fail fast on smoke checks before running the full suite. Treat every pending step as a tagged, tracked implementation task.

Before enabling agents to maintain step definitions, review shared-state access and move setup and teardown into hooks where needed. Keep refining scenarios as the application evolves. The goal is not a perfect suite before agents begin work, but a contract precise enough that failures do not invite ambiguous or destructive changes. In an agentic pipeline, specification quality is infrastructure.

Sources

  1. Spec-Driven Development:From Code to Contract in the Age of AI Coding Assistants

More in Behavior-Driven Development