Why compile-time Gherkin?
BDD makes a promise that almost everybody likes: readable specifications that double as executable tests.
Write the behaviour in Gherkin. Run it as a test suite. Ship with confidence.
The promise is real. The tooling that delivers it — Cucumber, JBehave, SpecFlow, Reqnroll, Behave, and friends — is also real, mature, and battle-tested. SpecBinder is not here to argue with any of that.
It is here to argue with a few specific choices that most runtime Gherkin tools share, and that start to hurt as a test suite grows.
The recurring pain
Most Gherkin runners follow the same recipe:
- Parse
.featurefiles at runtime. - Scan the classpath for step definitions tagged with
@Given/@When/@Then. - Match each step text against a regex or expression.
- Inject shared state through a DI container.
- Hand the whole thing to a custom test runner.
It works. It also produces a familiar set of complaints once a project grows past a few hundred scenarios:
- Undefined steps are runtime surprises. You only learn that a step has no match when the test runs.
- Ambiguous matches are worse surprises. Two regexes claim the same step, and your test silently runs the wrong code.
- The global step registry is a free-for-all. Every step definition is visible to every feature. Renaming one phrase can ripple across modules you've never opened.
- State is awkward. PicoContainer, Spring, Guice, or a hand-rolled
ScenarioContext— pick your poison. - Data tables are stringly typed.
row.get("price")returns aString. You parse, you cast, you hope. - IDE support is second-class. Find Usages, Rename, navigation — they all work almost as well as for plain Java. Almost.
These are not new observations.
Anyone who has shipped a large Cucumber-style suite has probably met at least three of them.
Possibly before coffee.
A different recipe
SpecBinder picks a single, opinionated swap: do all of that at compile time, not runtime.
A Java annotation processor reads your .feature or .specb files during javac and emits a plain JUnit 5 test class for each one. Every Given/When/Then becomes a strongly-named, statically-bound method call. No runner, no classpath scan, no regex matcher, no DI container..
The result is Gherkin automation that behaves much more like ordinary Java test code: visible to the compiler, navigable in the IDE, and executable by standard JUnit tooling.
What this section covers
The pages in this section walk through the main ideas one by one.
Compile-time safety
How missing steps, changed parameters, and type mismatches become javac problems instead of CI surprises.
Feature-scoped steps
Why SpecBinder avoids a global step-definition library by default, and how feature-scoped methods reduce accidental coupling between unrelated specifications.
Plain JUnit 5
How generated tests remain ordinary JUnit 5 tests, so IDE runners, CI reports, tags, lifecycle methods, and debugging continue to work as expected.
Simple state management
Why step state can just be Java state: fields, objects, page objects, API responses, calculated values, or captured exceptions.
No extra framework ceremony required.
Type-safe Data Tables
How SpecBinder applies the same compile-time model to Gherkin Data Tables, turning table rows into generated, type-aware Java objects.
TDD-friendly Gherkin automation
How generated test structure keeps the suite runnable and meaningful while a feature is still being built.
Green where you have finished.
Red where you have not.
Useful feedback all the way down.
What SpecBinder is not
A short list, to keep expectations honest:
- Not a Cucumber replacement for every project. If your current setup works well and your team is happy with runtime binding, that is a perfectly valid place to be.
- Not a different specification language. SpecBinder reads standard Gherkin using Cucumber's parser.
- Not a runtime framework. Tests run as plain JUnit 5. Maven, Gradle, Surefire, Failsafe, IntelliJ IDEA, and CI systems can treat them as Java tests.
- Not magic. Compile-time generation means you see some errors earlier. That is the benefit. It is also the cost.
The short version
SpecBinder focuses on one narrow part of the BDD toolchain:
turning formulated Gherkin specifications into maintainable, type-aware, JUnit-based automation.
If you like Gherkin, but would rather let the compiler find broken bindings before your test runner does, these articles explain the thinking behind the project.