top of page

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.

bottom of page