Keeps a BDD step-definition library DRY across a Cucumber / Behave / Reqnroll project - inventories every step definition, detects duplicates (different patterns matching the same intent), recommends canonical consolidations, reorganizes steps by domain, and publishes a step-library README the team greps for "is there already a step for X?" before authoring new ones. Use when a BDD project's step count grows past ~50, on a quarterly step-library review, or when a new engineer cannot find an existing step and is about to write a duplicate.
75
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
After 6 months of a BDD project, step definitions proliferate:
Given a user and Given a logged-in user
for the same fixture.The result: step library bloat → Gherkin features hard to read, step ambiguities, runtime errors, drift.
This skill builds a curation workflow.
Work through Steps 1-6 below in order: inventory -> detect duplicates -> recommend consolidations -> reorganize and publish the README -> gate new steps pre-merge -> repeat on a cadence.
Extract every declared step pattern across the project. Each runner
uses its own annotation syntax (@Given in Cucumber-JVM, @given
in Behave, [Given] in Reqnroll / SpecFlow) - the per-runner
extraction commands are in
references/step-extraction-and-overlap.md.
The inventory produces a step audit:
Total step definitions: 142
Unique patterns: 138 (4 ambiguous duplicates already)
Per Gherkin verb:
Given: 58
When: 34
Then: 47
And: 3Two patterns are likely duplicates when:
Given a user vs Given an existing user vs Given the user.When I click {label} vs
When I press {label} vs When I tap {label}.Given a cart with {n} items vs
Given a cart containing {n} items.Normalize each pattern (lowercase, drop articles, collapse parameters) and group by the normalized form; any group of size greater than one is a candidate cluster. The overlap script that does this is in references/step-extraction-and-overlap.md.
For each duplicate group:
**Duplicate group:** 4 step definitions with normalized "user is
logged in"
| Pattern | File / line |
|------------------------------------|----------------------------|
| `Given a user is logged in` | `auth_steps.py:12` |
| `Given the user is logged in` | `cart_steps.py:8` |
| `Given an authenticated user` | `checkout_steps.py:5` |
| `Given a logged-in user` | `profile_steps.py:14` |
**Recommendation:** Consolidate to **`Given a logged-in user`**
(highest count of usage in current Gherkin; clearest wording).
Replace the other 3 step definitions with a single canonical one
in `shared_steps.py`. Update the Gherkin features that use the
deprecated patterns.Verify: consolidation is destructive - it deletes step definitions and
rewrites .feature files. After each group, run the full BDD suite and assert
zero undefined or ambiguous steps and no orphaned scenarios before declaring the
refactor complete. If a scenario reports an undefined step, a .feature file
still references a deprecated pattern - fix that reference and re-run.
Group steps per domain area:
features/steps/
├── shared/ # cross-domain (login, navigation, etc.)
│ ├── auth_steps.py
│ ├── navigation_steps.py
│ └── data_steps.py
├── checkout/ # checkout-specific
│ ├── promo_steps.py
│ ├── payment_steps.py
│ └── cart_steps.py
├── account/ # account-specific
│ └── profile_steps.py
└── README.md # step library indexThe README is the discoverability artifact:
# Step library
## Shared (cross-domain)
### Auth
- `Given a logged-in user` (auth_steps.py:12) - creates and logs in a generic test user.
- `Given a logged-in admin` (auth_steps.py:25) - logged-in user with admin role.
- `Given an unauthenticated visitor` (auth_steps.py:38) - no session.
### Navigation
- `When I navigate to {path}` - go to URL.
- `When I click {label}` - click any element with this label.
## Checkout
### Cart
- `Given the cart contains {qty} of {sku} at ${price}` - seed a cart.
- `Given the cart is empty` - empty cart.
### Promo codes
- `Given promo code {code} is active` - pre-seed a promo in the admin.
- `When I enter {code} in the promo input` - type the code.
- `When I click {label}` - (uses shared step).
(...)The README + grep is the team's "is there a step for X?" tool.
Add a CI check that flags new step definitions so no engineer adds a
duplicate unknowingly. The check warns (doesn't block), forcing the
author to acknowledge the new step and grep the README first. The
check-new-steps.sh script is in
references/step-extraction-and-overlap.md.
| Cadence | Trigger |
|---|---|
| Quarterly | Scheduled step library review. |
| New team member | Onboarding: walk the README. |
| Step count exceeds threshold | Triggered review. |
| New domain area | Add steps; update README. |
Curating a 142-step library in a mixed Behave project, end to end.
1. Inventory. The Behave extraction over features/steps/ yields the
Step 1 audit: 142 step definitions, 138 unique patterns - so 4 are already
ambiguous duplicates the runner would flag at match time.
2. Detect. The overlap script surfaces one cluster - the four
user is logged in variants listed in Step 3's duplicate-group table.
3. Consolidate. Pick Given a logged-in user as canonical
(clearest wording, most-used in current Gherkin). Move it into
features/steps/shared/auth_steps.py, delete the other three
definitions, and rewrite the .feature files that used the
deprecated phrasings - edit the Gherkin first so no scenario is
left orphaned, then run the Step 3 verification.
4. Reorganize + publish. Split the flat features/steps/ into
shared/, checkout/, and account/, then regenerate the README
index. The library now advertises
Given a logged-in user (auth_steps.py) - creates and logs in a generic test user
under Shared → Auth.
5. Gate. Add the pre-merge new-step check. The next PR that adds
Given the customer is signed in trips the warning; the author greps
the README, finds Given a logged-in user, and reuses it instead of
adding a fifth variant.
Result: 142 → 139 step definitions, zero ambiguous duplicates, one discoverable index the whole team searches before writing a step.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
Per-engineer step files (alice_steps.py) | Ownership without domain alignment; duplication across files. | Domain-organized files (Step 4). |
| Step library README missing | Discoverability nil; engineers re-implement. | README per Step 4. |
| Ambiguous step deletion without grep | Breaks scenarios silently. | Replace canonical → deprecated; update all Gherkin first. |
Step "shared library" that's a giant helpers.py | All engineers conflict on it; merge hell. | Domain split (Step 4). |
| Reviewing step count quarterly only | Proliferation outpaces review; library bloats. | Pre-merge gate (Step 5). |
Given a user for auth vs Given a user with profile data for profile tests).cucumber-testing,
behave-testing,
reqnroll-testing - per-language
runners this curator works alongside.