Learning Objectives
By the end of this lesson you will be able to:
- Recognize multiple Gherkin smells stacked together in one real scenario
- Refactor a messy scenario into a clean one step by step, justifying each change
- Apply a full audit checklist to any scenario you inherit
The Messy Scenario
Here's a login scenario that could have come straight out of a rushed sprint. It has every smell this course has named, stacked on top of each other:
Scenario: User logs in
# TODO: ask Dana if we still need the "remember me" checkbox
Given the user is on the login page
When the user clicks the email field, types "dana@example.com", clicks the password field, types "Sup3rSecret!", and clicks the blue "Log In" button
And the user waits 2 seconds for the page to redirect
Then no errors appear in the browser console
And the dashboard heading is rendered in the same font as the login page
Then the request is processed
But an expired account is rejected on the next login attempt
At a glance it "looks like" a scenario. Read closely and it's a mess of every smell in this module.
Step by Step
1. The stray comment. # TODO: ask Dana if we still need the "remember me" checkbox is a developer's aside that never got resolved before the scenario shipped. It has nothing to do with the behavior being specified. Delete it — or better, resolve the question first and only then decide if a scenario needs updating.
2. The conjunction step. The When line does five things in one sentence: clicking the email field, typing an email, clicking the password field, typing a password, and clicking a login button. None of those sub-actions matter to the business rule being tested — logging in. Collapse it to one declarative action:
When the user logs in with valid credentials
3. UI-click language, twice over. "Clicks the blue 'Log In' button" ties the spec to a specific button color — a cosmetic detail that has nothing to do with the login behavior and will break the spec's readability, if not its automation, the day someone redesigns the button. It's already gone in the rewrite above. The redundant "waits 2 seconds for the page to redirect" is the same problem in a different outfit: it's an implementation detail about how the redirect happens, not a fact about what should happen. Delete it entirely — the Then step should confirm the outcome, not the mechanics of getting there.
4. Technical noise. "Then no errors appear in the browser console" is a legitimate thing to check somewhere — just not here. It's not a business outcome; it's an implementation health check. It doesn't belong in a scenario meant to be read by a BA. Delete it.
5. A cosmetic UI detail masquerading as a business outcome. "The dashboard heading is rendered in the same font as the login page" is a visual consistency check, not a login behavior. Delete it — this belongs in a visual regression or design-system test, not a Gherkin scenario about logging in.
6. Vague expected outcome. "Then the request is processed" says nothing observable. Replace it with an outcome someone could actually verify:
Then the user sees their dashboard
7. Scenario mixing. The trailing But an expired account is rejected on the next login attempt is an entirely separate case smuggled onto this scenario. Split it into its own scenario with its own full setup:
Scenario: Expired account is rejected
Given a registered user whose account has expired
When the user attempts to log in with valid credentials
Then the user sees an error message explaining the account has expired
The Clean Result
Scenario: User logs in
Given the user is on the login page
When the user logs in with valid credentials
Then the user sees their dashboard
Three lines. Every word earns its place. A BA can read it in five seconds and know exactly what's being promised.
Your Audit Checklist
When you inherit any scenario, run it through these questions:
- Does every step describe one action or one fact — no commas or "and" stitching multiple things together?
- Is the scenario under roughly ten lines? If not, does it test more than one business rule?
- Does every
Thenstep state an observable, specific outcome? - Is the language declarative (business actions), not UI-click language (buttons, fields, colors)?
- Is every assertion a business outcome, not technical noise (console errors, load times, fonts)?
- Is there a second, unrelated case glued on with
But? Split it out. - Are there any stray comments left over from drafting? Remove them.
Pro Tip: Refactor smells one at a time, in isolation, and re-read the scenario after each change. Fixing five smells simultaneously is how you accidentally delete a step the scenario actually needed.
Key Takeaways
- Real scenarios often stack multiple smells at once — the fix is to work through them one at a time, not all at once
- A clean scenario reads as three to five lines of pure business intent, with every implementation detail stripped away
- The audit checklist from this lesson applies to any scenario you inherit, in any course, from here on