Skip to main content

Configuration

SpecBinder's code-generation behaviour is controlled through the @Gherkin2JUnitOptions annotation.

Applying configuration

@Gherkin2JUnitOptions can be placed on:

  • The marker class itself — applies to that feature only.
  • A shared base class — applies to every marker class that extends it. The annotation is @Inherited, so subclasses pick the options up automatically.
@Gherkin2JUnitOptions(addSourceLineNumbers = true)
public abstract class BaseFeatureOptions {
}

@Gherkin2JUnit("specs/ShoppingCart.feature")
public abstract class ShoppingCartFeature extends BaseFeatureOptions {
}

Selective override

A child class can place its own @Gherkin2JUnitOptions to override only the options it explicitly sets. Every other option keeps the inherited value:

@Gherkin2JUnitOptions(
addSourceLineNumbers = true,
useStepKeywordInStepMethodName = true
)
public abstract class BaseFeatureOptions {
}

@Gherkin2JUnit("specs/ShoppingCart.feature")
@Gherkin2JUnitOptions(useStepKeywordInStepMethodName = false) // only this one changes
public abstract class ShoppingCartFeature extends BaseFeatureOptions {
}

In the example above, ShoppingCartFeature still inherits addSourceLineNumbers = true — only the keyword-in-method-name option is locally overridden.


Generation mode

shouldBeAbstractboolean, default true

Controls whether the generated test class is abstract (the default) or concrete.

  • true (default) — generates public abstract class <Name>Scenarios extends <MarkerClass>. Every step method is declared as abstract. You create a concrete subclass that overrides each step. Missing implementations are compile errors.
  • false — generates public class <Name>Test extends <MarkerClass>. Step methods have bodies (see unimplementedStepBehavior below). The class is immediately runnable; you implement steps by moving them into the marker class, where the generator will detect them and stop emitting stubs.

classSuffixIfAbstractString, default "Scenarios"

The suffix used for the generated class name when shouldBeAbstract = true. For a marker ShoppingCartFeature, the default produces ShoppingCartScenarios.

classSuffixIfConcreteString, default "Test"

The suffix used for the generated class name when shouldBeAbstract = false. For a marker ShoppingCartFeature, the default produces ShoppingCartTest.

unimplementedStepBehavior — enum, default FAIL

Only relevant when shouldBeAbstract = false. Controls the body of unimplemented step stubs in the generated concrete class:

ValueBody
FAIL (default)Assertions.fail("Step is not yet implemented") — test fails at run time when the step is hit.
SKIPAssumptions.assumeTrue(false, "Step is not yet implemented") — test is reported as skipped/aborted.
COMPILATION_ERRORA non-Java token is emitted so the project will not compile until the step is implemented. Useful if you want concrete mode's runnable class plus abstract mode's compile-time safety.

Empty Gherkin elements

emptyScenarioBehavior — enum, default FAIL

Behaviour for Scenario blocks that have no steps yet.

ValueBehaviour
FAIL (default)Emits Assertions.fail("Scenario has no steps").
SKIPEmits Assumptions.assumeTrue(false, ...) — reported as skipped.
COMPILATION_ERRORThe project will not compile until the scenario has steps.

emptyRuleBehavior — enum, default FAIL

Same three values; applies to Rule blocks that contain no scenarios.

tagForEmptyScenariosString, default "new"

JUnit @Tag value automatically added to empty scenarios. Set to "" to disable.

tagForEmptyRulesString, default "new"

JUnit @Tag value automatically added to empty rules. Set to "" to disable.


Data tables

dataTableParameterType — enum, default LIST_OF_OBJECT_PARAMS

Controls how Gherkin data tables are represented as parameters on the generated step methods.

ValueGenerated parameter typeNotes
LIST_OF_OBJECT_PARAMS (default)List<XxxParam> where XxxParam is a generated record-like inner classStrongest type safety. Column headers become typed fields with inferred types (String, Integer, Long, Double, Boolean, Character).
LIST_OF_MAPSList<Map<String, String>>All values are strings; convert at the call site.
CUCUMBER_DATA_TABLECucumber's io.cucumber.datatable.DataTableRequires getTableConverter() in the class hierarchy. Useful if you're already invested in Cucumber's data-table API.

With LIST_OF_OBJECT_PARAMS, the generator emits a typed wrapper:

Given my cart contains the following items:
| name | qty | price | category |
| Wireless Headphones | 1 | 60.00 | electronics |
public void myCartContainsTheFollowingItems(List<ItemsParam> items) {
// your implementation
}

public static class ItemsParam {
public String name() { /* ... */ return null; }
public Integer qty() { /* ... */ return null; }
public Double price() { /* ... */ return null; }
public String category() { /* ... */ return null; }
}

You can move the ItemsParam class up into the marker class and refine its field types — for example, changing String category to an enum Category. The generator then uses your refined class and the project fails to compile if a spec row contains an unknown category. This turns spec/data drift into a compile error.

useQualifiedEnumConstantsboolean, default false

When generated code references an enum constant in a LIST_OF_OBJECT_PARAMS table, controls whether the constant is referenced as AVAILABLE (with a static import — default) or Status.AVAILABLE (qualified by enum type name). The qualified form is more verbose but reads better when several enums are in play.


Step method naming

useStepKeywordInStepMethodNameboolean, default false

Controls whether the Gherkin keyword (Given/When/Then) is included as a method-name prefix.

Stepfalse (default)true
Given user existsuserExists()givenUserExists()
When user existsuserExists()whenUserExists()
Then user existsuserExists()thenUserExists()

The default collapses identical step text under different keywords into a single shared method — typically what you want.


Cucumber interop

addCucumberStepAnnotationsboolean, default false

When true, the generator adds @Given / @When / @Then annotations from io.cucumber.java.en.* on generated step methods. Useful if an IDE Cucumber/Gherkin plugin is in play and you want navigation from spec text → step method to work through those annotations.

useCucumberAnnotationsForStepMatchingboolean, default true

When true, the processor inspects Cucumber step annotations on methods in the class hierarchy to determine whether a step is already implemented — independent of method name. A method annotated with @Given("user exists") is recognised as the implementation of Given user exists even if the method itself is named setupUser.

Both regular expressions and Cucumber expressions are supported in the annotation value. Cucumber expressions support these built-in parameter types: {int}, {long}, {short}, {byte}, {float}, {double}, {bigdecimal}, {biginteger}, {word}, {string}, and the anonymous {}. Custom parameter types are not supported.

If both an annotation-matched method and a name-matched method exist for the same step, the annotation match wins.


Spec file discovery

supportedFileExtensionsString[], default {"feature", "specb"}

Extensions (without the leading dot) recognised by convention-based discovery (@Gherkin2JUnit with no value) and by glob patterns. When @Gherkin2JUnit("explicit/path.txt") provides an explicit path, the file is processed regardless of its extension.

skipGenerationForTagsString[], default {}

Regex patterns matched against tags on Feature / Rule / Scenario / Examples. When any tag on an element matches, the corresponding generated element (test class, @Nested rule, @Test method, or Examples row set) is omitted entirely — useful for excluding manual or work-in-progress specs without deleting them.

@Gherkin2JUnitOptions(skipGenerationForTags = {"manual", "wip-.*", "(?i)ignore"})

This would skip generation for elements tagged @manual, anything starting with @wip-, or @ignore (case-insensitive).


Generated code diagnostics

addSourceLineNumbersboolean, default false

When true, the generator embeds spec file line numbers in two places:

  • @DisplayName on scenarios, rules, and backgrounds — e.g. @DisplayName("Scenario [12]: Successful login").
  • The block comment above each step call — e.g. /* [13] Given user exists */.

Helpful when stepping through a generated test class and you want to jump back to the corresponding spec line.

emitScenarioHashboolean, default false

When true, each generated @Test / @ParameterizedTest method is annotated with @ScenarioHash("<sha-256-hex>") — a hash of that scenario's executable content (background steps + scenario steps, including DocStrings and DataTables). Useful for tooling that wants to detect when a scenario's meaning has changed across builds.


Build output

verbosity — enum, default NORMAL

Controls how much the annotation processor writes to the build log. Each level is cumulative — it emits everything from the levels below it.

LevelWhat it emits
SILENTErrors only. No banner, no summary.
NORMAL (default)Errors, warnings, startup banner, end-of-round summary.
VERBOSEAdds per-class headers, resolved feature paths, and reasons for skipped work.
DEBUGAdds full stack traces, parsed Gherkin AST summaries, JavaPoet model summaries, and per-step decisions.

The annotation-level setting overrides the global -Aspecbinder.verbosity=… annotation-processor argument.


Experimental

enableCompositeStepsboolean, default false

Enables composite steps, where a regular step followed by one or more *-prefixed sub-steps generates a wrapper method that delegates to the sub-steps via a lambda. Inspired by JBehave's textual composites.

Given customer "Alice" has product "Laptop" in shopping cart
* login as customer $p1
* search for product $p2
* add product to cart
* verify cart contains $p2

The generator emits a wrapper that lets the implementer either provide a custom default or run the listed sub-steps as the composite's body.

Experimental — API and exact code shape may change.


Quick reference

OptionDefault
shouldBeAbstracttrue
classSuffixIfAbstract"Scenarios"
classSuffixIfConcrete"Test"
unimplementedStepBehaviorFAIL
emptyScenarioBehaviorFAIL
emptyRuleBehaviorFAIL
tagForEmptyScenarios"new"
tagForEmptyRules"new"
dataTableParameterTypeLIST_OF_OBJECT_PARAMS
useQualifiedEnumConstantsfalse
useStepKeywordInStepMethodNamefalse
addCucumberStepAnnotationsfalse
useCucumberAnnotationsForStepMatchingtrue
supportedFileExtensions{"feature", "specb"}
skipGenerationForTags{}
addSourceLineNumbersfalse
emitScenarioHashfalse
verbosityNORMAL
enableCompositeStepsfalse (experimental)