A story’s acceptance criteria are met, the demo goes fine, and the feature disappoints the people it was for. The criteria were written from the solution: each one restates a piece of the design as a check, so a build that matches the design cannot fail them. A criterion worth writing names a situation the build can fail in.
A criterion written from the solution cannot fail
The story says a support agent needs to find a customer’s order. The design shows a search box on the orders page. The criteria say: a search box is shown on the orders page; typing an order number and pressing enter shows the matching order; a message is shown when nothing matches. All three are met at the demo. Then an agent on a call tries it with the customer’s email address, because customers do not know their order numbers, and gets the message.
Nothing in that story was done badly. The criteria were derived from the design rather than from the situation, so each one is a piece of the design restated as a check, and a build that matches the design passes them by construction. The developer built what was written and the tester checked it; the person the story was for was never in it.
That is the pattern behind most criteria that get met while the feature disappoints. Such a criterion fails only when the design was not built, and the design is what the developer was looking at all week.
Name the user, the situation and the outcome
Acceptance criteria that can fail name three things: who is acting, what situation they are in, and what they can observe at the end. “A support agent on a call, holding only the customer’s email address, reaches that customer’s most recent order without leaving the page” can be failed by a build that does everything the design says. That is what makes it a criterion rather than a description.
| Written from the solution | Written from the situation | How the second one fails |
|---|---|---|
| A search box is shown on the orders page | An agent holding only the customer’s email address reaches their latest order | The box accepts only order numbers |
| A message is shown when nothing matches | An agent who mistypes an email address sees the near matches, so they do not start over | The message says nothing was found and offers nothing |
| The export button downloads a CSV | A finance user opening the export in a spreadsheet sees one row per order with amounts as numbers | Amounts export as text with a currency symbol in front |
| The form validates the postcode | A customer typing a postcode with the space in the wrong place is not sent back to the start | Validation rejects the space and clears the form |
Every row on the right is longer, and every one of them can be checked by somebody who has never seen the design. That is the property that matters, because the person checking a criterion at acceptance is often a business user, and a criterion they cannot judge from the outside is not theirs to accept. A criterion in that shape is also a test scenario with almost no editing, and the tester writes the cases beneath it rather than inventing the situation themselves.
The disappointing situations were never written down
The happy path is the situation the design was drawn for, and it is the one criterion every story already has. Disappointment lives in the other situations, the ones a user reaches without meaning to, and a story that lists only its happy path has delegated every one of them to the developer’s judgement on the afternoon they were built.
| Situation | The question the criterion answers |
|---|---|
| First use, nothing there yet | What does the agent see before any order exists? |
| Wrong or partial input | What happens with an email address that matches two customers? |
| Interrupted | What does a refresh in the middle of a search leave on the screen? |
| Without permission | What does an agent outside the customer’s region get? |
| At the limit | What does the customer with four hundred orders see? |
| What must not happen | Can a search ever show another customer’s orders to this agent? |
Not every story needs every row, and a product owner who writes all six for every story will write nothing else. The last row is never optional. A criterion stating what must not happen is the one a design cannot supply, since a design shows what is there and says nothing about what must stay absent. The edge case nobody predicted will still arrive; the point of the table is that most of them are predictable, and the rows on it are the ones that come back as “it works, but”.
Who checks a criterion matters more than its format
Given/When/Then, a checklist, a sentence each: the format that gets argued about most changes least. A criterion in Given/When/Then written from the design still restates the design, with more words. What changes the outcome is who can check the criterion. Written from the situation, it can be checked by the person who has that situation: the support lead, the finance user, whoever stands in for the customer in a UAT round. Written from the solution, it can only be checked by somebody looking at the design, and that is the developer who built it.
That is also where a criterion’s failure gets lost. A business user checking the build against a situation sees that it disappoints and cannot say, in a ticket, which element is wrong or what the page did when they tried. In a review session the support lead marks the search box itself on the live page and writes the note against it; the note is stored with that element and enters Received as a ticket, so “it works, but” reaches the board with a page and an element on it rather than as a sentence in the meeting notes.
The product owner’s own check follows the same rule. Reading the criteria against the demo is a check of the solution; sitting with the support lead while they take a call is a check of the situation, and it is the only one of the two that finds the email address problem before the sprint review does.
Some criteria wait for the first working build
Part of the disappointment is a decision the product owner had not made, because the situation it belongs to was invisible until there was a build to look at. Whether the search should match a partial email address is a decision rather than an oversight, and it got made by the developer because nobody else was in the room when it came up.
The revision goes on the calendar. A story gets one round of criteria revision after the first working build and before acceptance, the story is accepted against the revised criteria and never the original ones, and the sprint holds the extra length that round adds. A criterion added after the first look is not scope creep when it names a situation that was always going to happen; it is the criterion that should have been there, arriving when the situation became visible.
What the team cannot do is accept the story against the original criteria and file the disappointment as a bug. A bug against a met criterion has no expected result to point at, and it will be closed as working as designed, which is what it is.