What are acceptance criteria? Writing them so QA can test

How to write acceptance criteria clear enough that QA knows exactly what to test, with a coupon example and ready-to-use templates.

Written by Phan Lam Duy Khoi

Acceptance criteria (AC) are the conditions a user story must meet to count as built correctly. They are testable when every line gives a clear pass or fail result, uses concrete values, and covers error cases, instead of words like “fast” or “easy to use”.

A ticket sent back over the word “fast”

This is an illustrative situation. You are the PO at Mây Shop, an online store selling tea and gifts. You write a user story for entering a coupon code at checkout, with three criteria: “Customers can enter a code easily”, “The system applies the code fast”, “Show a clear error when the code is wrong”. A developer finishes it in three days.

On day four, the QA tester messages you: “How many seconds is fast? What do we show when a code has expired? Can a 299,000đ order use a code meant for orders from 300,000đ? What if the customer removes items after applying the code?”

None of these questions is hard. But the ticket answers none of them. The developer picked one interpretation, QA is guessing another, and you are the only person who knows the answer, or thinks you do. Each question costs a round of messages, and if nobody asks, the bug goes straight to customers.

This article covers acceptance criteria: what they are, why they often cannot be tested even when written down, and how to write them so QA knows exactly what to try. For writing the user story itself, the “who needs what and why”, see the separate article below.

What are acceptance criteria?

Acceptance criteria, usually shortened to AC, are the conditions a user story must meet to count as built correctly. Each story has its own set. The story says who needs what and why. The AC say exactly what counts as done right.

Good AC have one easy-to-spot trait: every line produces a pass or a fail. Two different people reading the same line and testing the same build should reach the same conclusion. Agile Alliance describes acceptance tests in the same spirit: the result is pass or fail, and they are usually written as examples or usage scenarios.

AC serve three people at once. Developers use them to know where to stop. QA uses them to know what to try. The PO uses them to accept the work against a clear list, instead of a feeling that it “looks fine”.

A note on terms: the Scrum Guide does not define acceptance criteria. According to Scrum.org, they are not part of Scrum but a complementary practice many teams use for transparency. So teams write AC in different styles, which is fine as long as everyone on the team reads them the same way.

Why are acceptance criteria often untestable?

New POs rarely lack ideas when writing AC. The problem is that AC get written as a description of a wish, not as something a person will take and test. Five patterns come up again and again:

  • Feeling words. “Fast”, “easy to use”, “friendly”, “clear”, “smooth” describe how you want users to feel, not how the system behaves. Each reader assigns their own threshold.
  • Only the happy path. The writer imagines a customer entering a valid code on a qualifying order with a stable connection. Many bugs live on the other paths.
  • Solutions instead of results. “Show a popup” or “call the code-check API” describes how, but not what counts as passing. It also ties developers' hands when a better approach exists.
  • Business rules outside the ticket. The maximum discount, the expiry date, how many times a code can be used: these sit in the PO's head, in a marketing file, or in an old chat message.
  • Several conditions in one line. When a line holds three ideas and QA marks it failed, nobody knows which part broke.

A simple self-check: read each line and ask “What will QA do, and where will they look to know it passed?” If you cannot answer in one sentence, the line is not finished.

Untestable words and how to rewrite them
Common wordWhat QA will askHow to rewrite it
FastHow many seconds, measured from when to when?State a time limit agreed with developers, plus the start and end points of the measurement
Easy to useEasy for whom, doing what, in how many steps?Describe the location, the number of steps, or the task users complete without help
Clear errorWhich error, shown where, with what wording?List each error type with its exact message and where it appears
Valid, appropriateAccording to which rule?State the specific rule: format, limits, conditions
Works wellWhat does well mean?Split it into visible results: amounts, states, saved data

How to write acceptance criteria, step by step

You do not need a long meeting to write AC. For a medium-sized story, the four steps below usually fit into a morning, with most of the time going into steps 1 and 3.

Four steps to testable AC Steps 1 and 3 are where AC most often fall short.
  1. Gather the rules: Numbers, limits, conditions
  2. Write the main path: One successful scenario end to end
  3. Add errors and edges: Wrong, missing, expired, reused, at the limit
  4. Read with dev and QA: Fix anything that still needs guessing

When QA asks a question the AC do not answer, add a line to the AC. Do not just answer in chat.

Step 1, gather the rules. Before writing any sentence, list every number and condition: who it applies to, the minimum amount, the maximum, when it expires, how many uses are allowed. If a number is not decided yet, say so and name who will decide. That is an open question, not a blank for developers to fill.

Step 2, write the main path. Describe one successful use: where the user is, what they do, what the system shows. Use visible behaviour, such as “the total drops by 30,000đ” or “a Discount line appears under Subtotal”, rather than “the code is applied successfully”.

Step 3, add errors and edge cases. This makes the biggest difference, so it gets its own section below.

Step 4, read it with developers and QA. Read each line aloud; fifteen minutes is enough. Developers will point out what is hard or unexpectedly costly. QA will ask questions like the ones in the opening. Each question is a missing line. If a question changes the scope, decide on the spot: include it in this story, split it into another, or list it as out of scope.

Checklist or Given/When/Then: which format should you use?

There are two common ways to write AC. Either works, as long as each line is testable. Many teams use both in the same story.

Two ways to write AC Choose by how complex the rule is, not by habit.
  • Rule-based checklist: Each line is a short rule, marked pass or fail. Suits independent rules that do not depend on a previous state. “Codes are not case-sensitive.”
  • Given/When/Then: Each scenario has a starting state, one action and a result. Suits conditional logic, thresholds or several linked steps. “Given a 299,000đ cart, when the code is entered, then show that 1,000đ is missing.”

Given/When/Then is a scenario template: Given is the starting context, When is the action, Then is the observable result. Agile Alliance describes it as a template for writing acceptance tests for a user story. Tools such as Cucumber can read this format and run tests automatically, but you can use it as a thinking frame without any tool.

Many Vietnamese teams keep the three English keywords because developers and QA already know them, and write the content in Vietnamese. What matters is that each scenario has exactly one action under When. If you find yourself writing “when the customer enters the code, then removes items, then enters it again”, that is three scenarios.

A quick way to choose: if you can state a rule in one sentence without the word “if”, use the checklist. If it needs “if… then…”, use Given/When/Then.

Which error and edge cases should you cover?

Edge cases sit at the boundaries of a rule: exactly at the limit, just below it, empty data, repeated actions. You do not have to think of everything. Walk through the list below and keep the cases that could actually happen and cause real harm.

  • Wrong or missing data: typos, empty fields, extra spaces, wrong format.
  • Thresholds: exactly at the limit, one unit below, above the cap.
  • Time and quantity: expired, not started yet, no uses left, out of stock.
  • Reuse and duplicates: second use, double-clicking the button, two tabs open at once.
  • Interaction with other features: another code already applied, items on sale, delivery fees, loyalty points.
  • Changes midway: the cart changes after the code is applied, the customer goes back a step.
  • Account state and permissions: guest checkout, new accounts, locked accounts.
  • System failures: lost connection, the payment service not responding, an interrupted action.

The two best sources for edge cases are QA and customer support. QA is used to thinking about how things break. Customer support knows where real customers get stuck. Ask them one question: “With this feature, what do customers do that we would not expect?”

For each error, the AC should say three things: whether the system blocks or allows the action, what the user sees (the exact message if it is agreed), and whether any data changes.

Example: rewriting AC for a coupon feature

Back to Mây Shop. This is an illustrative example; the rules and numbers are made up for practice. After gathering the rules in step 1, you have: the code MAY10 gives 10% off orders with a subtotal of 300,000đ or more (excluding delivery), capped at 50,000đ, one use per account, expiring at 23:59 on 30 November, and only one code per order.

AC before and after rewriting, illustrative example
Original ACProblemTestable AC
Customers can enter a code easilyDoes not say where the field is or what input is acceptedThe code field sits in the checkout step, just above the Total line. Codes are not case-sensitive, and leading or trailing spaces are ignored.
The system applies the code fastNo threshold to measureAfter tapping Apply, the total updates without a page reload, within 2 seconds (an assumed number agreed with developers).
10% off qualifying ordersDoes not define qualifying, has no capOrders with a subtotal of 300,000đ or more get 10% off, up to 50,000đ. Delivery fees do not count toward the subtotal.
Show a clear error when the code is wrongError types not separated, no wordingThree separate messages: code does not exist, code has expired, order below the minimum with the amount still missing.
NoneMisses reuseIf the account has already used MAY10 on a placed order, the code cannot be applied again and a message says it has been used.
NoneMisses cart changesIf the customer removes items and the subtotal falls below 300,000đ, the code is removed, the total updates and a message explains why.

Three lines became six, but each line now has a pass or fail result. The last two are where bugs easily appear: a customer reusing the code, or applying it and then removing items to get a discount on an order that no longer qualifies.

The threshold and the cap read more clearly as Given/When/Then, because they are conditional logic:

  • Scenario 1, exactly at the limit. Given a cart with a subtotal of 300,000đ. When the customer enters MAY10 and taps Apply. Then the Discount line shows 30,000đ and the Total drops by 30,000đ.
  • Scenario 2, below the limit. Given a cart with a subtotal of 299,000đ. When the customer enters MAY10 and taps Apply. Then the code is not applied and a message says the order needs 1,000đ more.
  • Scenario 3, at the cap. Given a cart with a subtotal of 600,000đ. When the customer enters MAY10 and taps Apply. Then the Discount line shows 50,000đ, not 60,000đ.

QA can read these three scenarios and know which cart to build, what to tap and where to look. Developers know they must handle the cap. Nobody needs to come back to you with questions.

How are acceptance criteria different from the Definition of Done?

These two are often mixed up. In short: AC belong to one story, while the Definition of Done (DoD) is a shared standard for all of the team's work. The Scrum Guide describes the DoD as a formal description of the state of the Increment when it meets the required quality measures, and work that does not meet it cannot be released.

Acceptance criteria and the Definition of Done
AspectAcceptance criteriaDefinition of Done
Applies toOne specific user storyAll of the team's work
Mainly owned byThe PO, written with developers and QAThe whole team, sometimes following an organisation standard
How often it changesDifferent for each storyStable across many sprints
ExampleOrders under 300,000đ cannot use MAY10Code reviewed; every AC checked by QA on staging

A story is done only when it meets both: its own AC and the team's DoD. If you find yourself copying “unit tests written” into every story's AC, that line belongs in the DoD. The article on the Definition of Ready and Definition of Done covers how teams build a DoD in more depth.

AC templates you can use today

The two templates below fit most stories. The first is a checklist so you do not forget a section. The second is a Given/When/Then frame for conditional rules. Copy them and delete whatever does not apply to your story.

AC checklist for a user story
Story: [story name or link]

Business rules (numbers, limits, conditions):
- [rule 1]
- [rule 2]

Main path:
- [ ] When [the user does what], the system [shows, saves or sends what]

Errors and edge cases:
- [ ] Wrong or empty input: [result]
- [ ] Exactly at and just below the limit: [result]
- [ ] Expired, no uses left, reused: [result]
- [ ] Combined with other features: [result]
- [ ] Changes midway: [result]
- [ ] Network or system failure: [result]

Messages shown (exact wording):
- [message 1]

Out of scope this time:
- [what is not included]

Open questions (who answers, by when):
- [question]
Given/When/Then frame
Scenario: [short name, e.g. Order exactly at the minimum]
Given: [who, where, what the starting data is]
And: [extra condition, if any]
When: [one single action]
Then: [a visible or checkable result]
And: [further results: amounts, messages, saved data]

Scenario: [the matching error case]
Given: [starting state]
When: [action]
Then: [whether the system blocks or allows it, what the user sees]

The “Open questions” section is worth keeping. It shows the whole team what is still undecided, instead of leaving developers to guess and the gap to surface during testing.

Five common mistakes when writing AC

  • Writing AC after the work is built. At that point they only describe what already exists and help nobody build it right. Write them before the story enters the sprint, or at least before development starts.
  • Writing too much for one story. If the AC run to twenty or thirty lines, the story is probably too big. Consider splitting it, for example separating applying a code from reporting on code performance.
  • Specifying the interface pixel by pixel. Button colours, spacing and font sizes belong to the design. Point the AC at the approved design, then focus on behaviour and rules.
  • Answering QA in chat without updating the ticket. Two weeks later nobody remembers what was agreed, and new team members only read the ticket.
  • Treating AC as the PO's private job. You own them, but writing alone means missing exactly the cases developers and QA see most clearly.

Summary

  • Acceptance criteria are the conditions a user story must meet. Every line should give a pass or fail result.
  • Replace feeling words such as “fast”, “easy to use” and “clear” with behaviour, numbers and exact wording.
  • Write in four steps: gather the rules, write the main path, add errors and edges, read it with developers and QA.
  • Use a checklist for simple rules and Given/When/Then for conditional logic or thresholds.
  • AC belong to each story; the Definition of Done is the team's shared standard. A story is done only when it meets both.

I am writing more PO situations in this same format, with templates you can use straight away. If you would like the next one by email, subscribe to the newsletter below.

Frequently asked questions

What are acceptance criteria?

Acceptance criteria (AC) are the conditions a user story must meet to count as built correctly. Each line should give a pass or fail result, so developers, QA and the PO reach the same conclusion.

Who writes acceptance criteria?

The Product Owner is usually mainly responsible for acceptance criteria, but should write them with developers and QA. Developers see technical limits, and QA sees the error cases a writer tends to miss.

What is the difference between acceptance criteria and the Definition of Done?

Acceptance criteria belong to one user story and say what that feature must do. The Definition of Done is a shared quality standard that applies to all of the team's work, such as code reviewed, tested and documented.

Sources to check

Related articles