Skip to main content

Gherkin → JUnit 5 Mapping

A reference table for what each Gherkin construct becomes in the generated JUnit 5 code. For runnable examples of each pattern, see the Examples section.

Primary keywords

GherkinJUnit 5 output
Feature: Customer checkout
in specs/Checkout.specb, pointed at by a class named ShopSpecs
public abstract class CheckoutScenarios extends ShopSpecs, in package specs, with @DisplayName("Feature: Customer checkout")
Feature description (free text under Feature:)JavaDoc on the generated class
Background: (feature-level)@BeforeEach public void background(TestInfo testInfo) { … } on the outer class
Background: (rule-level)@BeforeEach public void ruleBackground(TestInfo testInfo) { … } on the @Nested rule class
Rule: R1@Nested @DisplayName("Rule: R1") public class Rule_N { … }
Rule descriptionJavaDoc on the nested class
Scenario: S1 (top level)@Test @DisplayName("Scenario: S1") public void scenario_N()
Scenario: S1 (inside a Rule)@Test @DisplayName("Scenario: S1") public void rule_M_scenario_N() on the nested class (scenario numbering restarts per rule)
Scenario Outline: … + Examples:@ParameterizedTest with one @CsvSource(textBlock = …) per Examples block
Examples: rowOne iteration of the parameterized test
Where the generated class name and package come from

Four different names appear in the row above, and it is worth being explicit about which one drives what:

This……decides
Spec file nameCheckout.specbthe generated class nameCheckoutScenarios
Spec file's folderspecs/the generated packagespecs
The class you annotate — ShopSpecswhat the generated class extends
The Feature: titleCustomer checkoutthe @DisplayName only

So the class name comes from the file, never from the Feature: title and never from the class you annotate. Renaming the spec file renames the generated class with it.

The suffix is Scenarios by default, or Test in concrete mode; both are configurable via classSuffixIfAbstract / classSuffixIfConcrete.

Secondary keywords

GherkinJUnit 5 output
Given <text>Abstract / inherited / annotated method call inside the @Test method
When <text>Same — keyword does not change the method signature (unless useStepKeywordInStepMethodName = true)
Then <text>Same
And <text> / But <text>Same — inherits the keyword of the preceding Given / When / Then
Step "quoted" argumentString / Integer / Long / Double / Boolean / Character parameter (type inferred), with $p1, $p2, … slot in the method name
Step <placeholder> (Scenario Outline)Parameter from the Examples table — column header → parameter name, value → inferred type
Step <DocString> (triple-quoted)Trailing String parameter, value emitted as a Java text block
Step <DataTable>List<XxxParam> (default), List<Map<String, String>>, or io.cucumber.datatable.DataTable — see Data Tables

Tags

GherkinJUnit 5 output
@smoke on a Feature@Tag("smoke") on the generated outer class
@smoke @regression on a Feature@Tags({@Tag("smoke"), @Tag("regression")})
@ui on a Rule@Tag("ui") on the nested rule class
@happy-path on a Scenario@Tag("happy-path") on the @Test method

Comments and ordering

GherkinJUnit 5 output
Original step textPreserved verbatim in a multi-line block comment above each step call — the step text (e.g. Given user exists) sits on its own line between /* and */
Feature-file orderPreserved using @Order(N) annotations on rules and scenarios
Line numbers (when addSourceLineNumbers = true)Embedded in @DisplayName and prefixed to the step text inside its block comment — e.g. @DisplayName("Scenario [12]: …") and a comment line reading [13] Given user exists

Empty / incomplete elements

GherkinJUnit 5 output
Rule: with no scenariosA failing @Test public void noScenariosInRule() on the nested class, tagged @new by default (see tagForEmptyRules)
Scenario: with no stepsA failing @Test calling Assertions.fail("Scenario has no steps"), tagged @new by default

Behaviour is configurable via emptyRuleBehavior and emptyScenarioBehavior:

  • FAIL (default) — emit a failing assertion
  • SKIP — emit an Assumptions.assumeTrue(false, …) so the test is reported as aborted
  • COMPILATION_ERROR — emit a non-Java token so the project will not compile

See Configuration → Empty Gherkin elements for full details.

Step name derivation

The same Gherkin step under different keywords reuses the same method (unless useStepKeywordInStepMethodName = true):

Step textGenerated method name
Given user existsuserExists()
When user existsuserExists() — same method
Then "alice" is signed in$p1IsSignedIn(String p1)
Then "alice" has "3" items$p1Has$p2Items(String p1, Integer p2)
Given my cart contains the following products: (with a data table)myCartContainsTheFollowingProducts(List<ProductsParam> products)

Marker class lookup

For every step the generator processes, it first searches the marker class hierarchy for an existing implementation:

  1. By method name — derived as above
  2. By annotation pattern (Cucumber @Given / @When / @Then annotations on parent methods) — when useCucumberAnnotationsForStepMatching = true; off by default, opt in when migrating from Cucumber-based projects that rely on annotation values rather than method names

If a match is found, no abstract declaration (or stub) is emitted for that step. The generated @Test method simply calls the inherited implementation.

See also

  • Configuration — every @Gherkin2JUnitOptions flag that influences the mappings above.
  • Examples — a runnable Maven project per mapping pattern.