Config Inheritance
Share generation options across many marker classes via @Gherkin2JUnitOptions on a base class. Override specific options per marker as needed.
Source: examples/common-use-cases/example-7 on GitHub.
What this demonstrates
@Gherkin2JUnitOptionson a base class applies to every marker class that extends it- The annotation is
@Inherited— child classes pick up all options automatically - A child class with its own
@Gherkin2JUnitOptionsoverrides only the options it explicitly sets — unspecified options keep their inherited value - One base class can standardise generation behaviour across a whole project
- Both effects show up in the concrete tests: the class they extend and the step method names they implement
Directory layout
The shared base class sits at the top; each feature gets its own sub-package holding its marker, spec and test, so the package structure mirrors the inheritance hierarchy:
src/test/java/.../optionsinheritance/
├── BaseFeature.java ← shared @Gherkin2JUnitOptions
├── shoppingcart/
│ ├── ShoppingCartFeature.java ← marker, inherits all options
│ ├── ShoppingCart.specb
│ └── ShoppingCartTest.java
└── checkout/
├── CheckoutFeature.java ← marker, overrides one option
├── Checkout.specb
└── CheckoutTest.java
With one spec per sub-package, both markers use a bare @Gherkin2JUnit and discover their spec by convention.
Class hierarchy
BaseFeature.java (@Gherkin2JUnitOptions — shared options)
├── ShoppingCartFeature.java (inherits all options)
│ └→ ShoppingCartSpec.java (generated, abstract — "Spec" suffix, keyword-prefixed steps)
│ └→ ShoppingCartTest.java
└── CheckoutFeature.java (@Gherkin2JUnitOptions — overrides useStepKeywordInStepMethodName)
└→ CheckoutSpec.java (generated, abstract — "Spec" suffix, plain step names)
└→ CheckoutTest.java
How options flow
@Gherkin2JUnitOptions(
useStepKeywordInStepMethodName = true,
classSuffixIfAbstract = "Spec"
)
public abstract class BaseFeature {
}
// in shoppingcart/
@Gherkin2JUnit
public abstract class ShoppingCartFeature extends BaseFeature {
// Inherits everything from BaseFeature
}
// in checkout/
@Gherkin2JUnitOptions(useStepKeywordInStepMethodName = false) // only this is locally set
@Gherkin2JUnit
public abstract class CheckoutFeature extends BaseFeature {
// Still inherits classSuffixIfAbstract = "Spec"
}
| Option | BaseFeature | ShoppingCartFeature | CheckoutFeature |
|---|---|---|---|
useStepKeywordInStepMethodName | true | inherited (true) | overridden (false) |
classSuffixIfAbstract | "Spec" | inherited ("Spec") | inherited ("Spec") |
Options are inherited along the class hierarchy, not the package structure — the markers live in sub-packages and still
pick up everything from BaseFeature.
Effect on the generated code
// ShoppingCartSpec — inherits both options: "Spec" suffix, keyword-prefixed step methods
public abstract class ShoppingCartSpec extends ShoppingCartFeature {
public abstract void givenIHaveAnEmptyShoppingCart();
public abstract void whenIAdd$p1ToTheCart(String p1);
public abstract void thenTheCartShouldContain$p1Item(Integer p1);
}
// CheckoutSpec — overrides the keyword option, still inherits the suffix
public abstract class CheckoutSpec extends CheckoutFeature {
public abstract void iHaveACartWith$p1Items(Integer p1);
public abstract void iProceedToCheckout();
public abstract void iPayWithCard$p1(Long p1);
public abstract void theOrderShouldBeConfirmed();
}
The concrete ShoppingCartTest and CheckoutTest extend ShoppingCartSpec and CheckoutSpec and implement those
methods under exactly these names.
Run it
cd examples/common-use-cases/example-7
mvn test