Q21 of 21 · BDD / Cucumber
How do you write step definitions that are reusable without becoming too generic or ambiguous?
Short answer
Short answer: Write steps at the right level of abstraction — specific enough to be meaningful in context, general enough to be reused across scenarios in the same feature area. Avoid mega-generic steps like 'the user does something'; prefer domain-specific verbs.
Detail
Too specific — can't reuse:
When alice@example.com clicks the login button on page /login
The step is bound to one user, one URL, and one element — nothing else can reuse it.
Too generic — meaningless:
When the user performs an action
This conveys nothing about behaviour.
Right level of abstraction:
When the user logs in with valid credentials
When the user logs in with email {string} and password {string}
The first is reusable across happy-path scenarios. The second is parameterised for boundary/negative testing.
Parameterisation for reuse:
@When("the user submits the {string} form with {string}")
public void userSubmitsForm(String formName, String data) {
formHelper.submit(formName, data);
}
Step definition organisation: Group step definitions by domain area, not by feature file:
stepdefs/
AuthSteps.java ← all login/logout/register steps
OrderSteps.java ← all order-related steps
CommonSteps.java ← navigation, generic assertions
The "one step definition, multiple features" test: If a step is referenced in only one feature file, it may be too specific. If it's referenced in 5+, check it's still specific enough to be meaningful.
Avoid "AND soup":
# BAD — 8 And steps doing unrelated things
When the user clicks and waits and scrolls and types and submits
Each compound action should be its own named step with a clear behaviour label.