Acceptance Criteria: Given-When-Then Done Right
- Contributor
- Mar 11
- 5 min read
Given-When-Then is the most-recognized format for acceptance criteria. It comes from BDD but has spread far beyond it. Used well, it makes acceptance criteria precise. Used badly, it dresses up the same vague criteria in a more formal-looking outfit.
This guide is how to use Given-When-Then to actually produce better criteria.
The Format
Given [precondition]
When [action]
Then [outcome]
Three parts:
Given: what's true before the scenario starts
When: the action that triggers the scenario
Then: what should be observed after
Optional extensions:
And: additional Given, When, or Then conditions
But: negative conditions
Why It Helps
The structure forces specificity in three dimensions:
What state precedes the action?
What exactly is the action?
What exactly should happen?
Without this structure, criteria collapse into vague statements: "Sign-in works." Sign-in for whom, with what credentials, producing what result?
A Worked Example
A simple criterion:
Given a registered user with verified email
When they sign in with valid credentials
Then they are redirected to the dashboard
And a session is created
What this captures:
Specific precondition (registered AND verified)
Specific action (sign-in with valid credentials)
Specific outcomes (redirect + session)
What it doesn't lock in:
The UI of the sign-in form
The session storage mechanism
The exact dashboard URL
The criterion describes behavior; implementation is open.
Multiple Scenarios per Story
One story usually has multiple scenarios. Each scenario uses its own Given-When-Then.
Story: User sign-in
Scenario: Successful sign-in
Given a registered user with verified email
When they sign in with valid credentials
Then they are redirected to the dashboard
And a session is created
Scenario: Invalid credentials
Given a registered user
When they sign in with wrong password
Then they see an "invalid credentials" message
And no session is created
Scenario: Unverified email
Given a registered user with unverified email
When they sign in with valid credentials
Then they see an "email verification required" message
And are redirected to the verification flow
Scenario: Account locked
Given a registered user
And the account has 5+ failed sign-in attempts in the last hour
When they sign in with valid credentials
Then they see an "account locked" message
And no session is created
Four scenarios, four uses of Given-When-Then. Each scenario is one specific behavior.
What to Put in Given
The state that's true before the action. Specific.
Bad: "Given a user"
Better: "Given a registered user with verified email"
The Given describes preconditions specifically enough that the team can reproduce the state for testing.
Multiple Givens are fine when needed:
Given a registered user
And the user has admin permissions
And the workspace has billing enabled
But beware: many Givens often signal that the scenario is too complex. Consider whether it's actually two scenarios.
What to Put in When
The single action that triggers the scenario.
Bad: "When the user logs in and views the dashboard and edits their profile"
That's multiple actions, multiple scenarios.
Better:
Scenario: User edits profile
Given a signed-in user
When they update their display name to "New Name"
Then the display name in the header updates
One scenario per action. Keep When focused.
What to Put in Then
The observable outcomes.
Bad: "Then it works"
Better:
Then the user is redirected to /dashboard
And a session cookie is set
And the analytics event "user_signed_in" is fired
Multiple outcomes are fine. The discipline: each is observable. Anything not observable shouldn't be in the criterion.
Negative Cases (And Edge Cases)
A trap: only writing happy-path scenarios.
Scenario: Sign-in with empty email
Given the sign-in page is open
When the user submits with empty email field
Then a validation error is shown
And the form is not submitted
Each edge case is its own scenario. The story has many.
Common Mistakes
Implementation in Then. "Then a row is inserted into the sessions table." That's implementation. Better: "Then the user has an active session." How that's stored is engineering's choice.
Vague When. "When the user does the thing." Be specific about the action.
Conditional Then. "Then maybe X happens, or maybe Y, depending on..." That's two scenarios. Split.
Then includes new actions. "Then the user can also click X." That's the next scenario.
Past tense When. "When the user has clicked submit." Use present: "When the user clicks submit." (Some teams prefer past for the recorded action; pick a convention and stick with it.)
Gherkin Syntax
When used with BDD tools (Cucumber, SpecFlow), the format becomes Gherkin:
Feature: User Sign-In
Scenario: Successful sign-in
Given a registered user with verified email
When they sign in with valid credentials
Then they are redirected to the dashboard
The keywords (Feature, Scenario, Given, etc.) are part of the syntax. Steps map to code (step definitions).
Even without BDD tools, the Gherkin-style format is useful as plain text for acceptance criteria.
Scenario Outlines
For criteria that vary by inputs:
Scenario Outline: Sign-in with various credentials
Given a registered user with email <email>
When they sign in with password <password>
Then the result should be <result>
Examples:
| email | password | result |
| valid@test.com | correct | dashboard |
| valid@test.com | wrong | error message |
| bad-email | anything | format error |
Useful when the same scenario shape has many specific data variants.
When Given-When-Then Doesn't Fit
Some criteria don't fit naturally:
Cross-cutting non-functional criteria. "The system loads in under 2 seconds." There's no specific action.
Stylistic or visual criteria. "Matches the design mockup." Difficult to fit into the format naturally.
Permission lists. "Admins can do X, Y, Z; standard users can do X." Lists of capabilities don't fit Given-When-Then per capability.
For these, write criteria in plain bullets. Don't force the format.
Reading Criteria Aloud
A useful check: read criteria aloud. If they sound natural, good. If they're awkward, refine.
Bad: "Given the system is in the state where user authentication has occurred"
Better: "Given the user is signed in"
The format shouldn't make criteria unreadable. Plain English with the structure.
How Many Per Story
A working range: 3-7 scenarios per story.
Fewer than 3: the story may be too small, or you're missing edge cases
More than 7: the story may be too large; consider splitting
This isn't a hard rule, but it's a useful prompt.
Connecting to Tests
In a BDD setup, Given-When-Then criteria become executable tests directly.
In a non-BDD setup, the criteria still inform tests: each scenario typically becomes a test case.
Either way, the criterion-to-test mapping should be tight. A criterion without a verifying test is incomplete.
Anti-Patterns
Empty ceremony. Using Given-When-Then for criteria that don't need the structure (e.g., visual styling). Adds words without value.
Implementation creep. Specifying database tables, exact UI elements, internal API calls. Locks in solutions.
Mega-scenarios. One scenario covering everything from sign-in to checkout. Should be multiple.
Vague language. "Then it works correctly." The format doesn't fix vagueness; you have to.
Key Takeaway
Given-When-Then is a format for acceptance criteria: precondition, action, expected outcome. Used well, it makes criteria specific and testable. Multiple scenarios per story cover happy paths and edge cases. Keep When focused on a single action; keep Then on observable outcomes; keep implementation out. Don't force the format where it doesn't fit — some criteria work better as plain bullets. The discipline of the format matters more than the format itself.
Related reading
Keep learning. This article is part of the Software Testing Foundations path in the ShiftQuality Learning Center. Learn to design tests that catch real bugs.


