Write user stories that follow INVEST and give them testable Given/When/Then acceptance criteria.
Why it matters
On agile teams most requirements arrive as user stories: short statements of something a user wants to do and why. A story on its own is a promise of a conversation, not a specification. What makes it buildable and testable is its acceptance criteria. Analysts spend a lot of their time writing and refining both.
The story format
The common template is:
As a <type of user>,
I want <some goal>,
so that <some reason>.
For Riverside Library:
As a library member,
I want to see which rooms are free on a given day,
so that I can choose a time without phoning the desk.
Each part does a job. The role reminds the team who they are building for. The goal says what, not how ("see which rooms are free", not "a calendar widget"). The reason explains the value, and often helps the team find a simpler solution.
Card, conversation, confirmation
Ron Jeffries, one of the creators of Extreme Programming, described a story as three Cs. The card is the short written statement, small enough to fit on an index card. The conversation is the discussion between the product owner, the analyst, developers and testers that fills in the details; it happens close to when the story is built, so it uses the latest knowledge. The confirmation is the set of acceptance criteria that shows the story is done. An analyst's job is to make sure all three exist. A story with no conversation gets built on guesses, and a story with no confirmation is never clearly finished.
INVEST: what makes a good story
| Letter | Meaning | Library example of breaking it |
|---|---|---|
| I | Independent: can be built in any order | "Cancel a booking" written so it needs "edit booking" first |
| N | Negotiable: details agreed in conversation | A story that dictates the exact screen layout |
| V | Valuable to a user or the business | "Set up the database" (a task, not a story) |
| E | Estimable: the team can size it | "Improve bookings" (too vague) |
| S | Small: fits in one sprint | "Online booking system" (an epic) |
| T | Testable: you can tell when it is done | "Booking should be easy" |
A story that is too big is an epic. You split epics into stories, for example by workflow step (search, book, cancel), by user type (member, librarian) or by rule (single booking first, recurring bookings later).
Acceptance criteria with Given/When/Then
Acceptance criteria are the conditions a story must meet to be accepted. The Given/When/Then format, from behaviour-driven development (BDD) and its Gherkin language, makes them precise:
- Given the starting situation (context),
- When the user does something (action),
- Then the result you can observe (outcome).
For the "see free rooms" story:
Scenario: Member sees free rooms for a day
Given Room A is booked from 10:00 to 12:00 on 14 March
And Rooms B and C have no bookings on 14 March
When a member views availability for 14 March
Then Room A is shown as unavailable from 10:00 to 12:00
And Rooms B and C are shown as free all day
Scenario: Member picks a date in the past
Given today is 10 March
When a member views availability for 9 March
Then they see the message "Choose today or a future date"
Each scenario is a test. A tester, a developer and the sponsor can all read it and agree whether the software passes. Testers can later automate these scenarios with tools that read Gherkin.
A second story
As a librarian,
I want the system to refuse a booking that overlaps an existing one,
so that two groups never turn up for the same room.
Scenario: Overlapping booking is refused
Given Room B is booked from 14:00 to 16:00 on 20 March
When a member tries to book Room B from 15:00 to 17:00 on 20 March
Then the booking is not saved
And the member sees "Room B is already booked from 14:00 to 16:00"
Scenario: Back-to-back booking is allowed
Given Room B is booked from 14:00 to 16:00 on 20 March
When a member books Room B from 16:00 to 17:00 on 20 March
Then the booking is saved
The second scenario catches an edge case that would otherwise be argued about later: does ending at 16:00 overlap starting at 16:00? Writing it down settles it.
Tips for criteria
- Use concrete examples (real times, names, numbers), not "a valid booking".
- Cover the happy path, at least one failure, and the edge cases.
- Describe behaviour, not the user interface: "sees a message", not "a red toast appears top right".
- Keep each story to roughly 3 to 7 scenarios. More usually means the story should be split.
Common mistakes
- Stories that are tasks: "As a developer I want a bookings table". Users do not want tables.
- Missing "so that", which hides the value and blocks simpler ideas.
- Criteria written after the build, so they describe what was built instead of what was needed.
- Vague outcomes: "Then it works".
Quick recap
- A story states who wants what and why; the acceptance criteria make it testable.
- Check stories against INVEST; split epics into small, valuable stories.
- Given/When/Then scenarios with concrete examples cover the happy path, failures and edge cases.
Try it
Open the Do tab and write three stories with Given/When/Then criteria for your own process.