What acceptance criteria do
Acceptance criteria (AC) describe conditions a completed change must satisfy. They help the requester, developer and tester agree on the outcome. They are different from implementation instructions: “use a React hook” may be a technical constraint, but it does not tell anyone whether the user can complete the task.
Good criteria name an observable behaviour, the relevant context and a result that can be checked. “Make exports fast” is too vague. The team must first agree on a target and a measurement method.
The ticket describes the problem and scope. AC describe the conditions for accepting the result. A team’s Definition of Done covers shared delivery standards such as review and testing; it does not replace task-specific AC. A small change may need one or two criteria, while a flow with roles and errors may need more. Count only conditions that help someone decide whether the work is complete.
A requirement is not an assumption
“Add a customer export” does not say CSV, administrators only, a 10,000-row limit or a file named clients.csv. Those are missing decisions. A known requirement is stated and agreed. An assumption is a proposed answer without confirmation. A recommendation suggests an option and explains why; it still needs a decision before it becomes an AC.
For performance, do not turn “fast” into “under two seconds” on your own. Ask for a target and test conditions. If the requirement says “Exporting up to 10,000 records finishes within ten seconds,” then that can become a measurable criterion.
Feature: exporting a report
Weak: “Users can easily export all data.” This leaves permissions, filters, format and empty results open.
Better, once those decisions are confirmed:
- A user with the Reports permission can download a CSV containing all rows matching the current filters, including rows beyond the visible page.
- The CSV contains the agreed columns in the agreed order and uses UTF-8 encoding.
- When no rows match, the user receives a CSV with headers and no data rows.
Do not silently add the second or third condition to a real ticket. Ask the owner whether that is the intended behaviour first.
Bug: an intermittent sign-in failure
Weak: “Login works again.” A tester cannot know which failure has been fixed.
Better: “Given a valid account with two-factor authentication enabled, when the user submits the correct code after a password reset, then the session opens and the reported error does not occur.” This only works if the original failure can be reproduced under those conditions. Record the environment and reproduction steps in the ticket.
Technical task: upgrading an API
Weak: “Upgrade the billing API to v2 without breaking anything.” “Anything” cannot be verified.
Better:
- The billing client uses the v2 endpoint in the target environment.
- Existing invoice export requests still return the agreed fields and status codes.
- The affected integration tests pass against the v2 test environment.
The version and target environment are scope or constraints; the last two points describe evidence that the change works.
When Given / When / Then helps
Use Given / When / Then when the order of a user action and system response matters, or when several conditions change the outcome. It makes a sign-in flow easier to discuss. It adds little to a one-line copy change such as “The checkout button reads ‘Place order’.” Do not force every criterion into Gherkin.
When an upgrade from PHP 8.2 to 8.4 is the task, list the supported runtime, affected integrations and required checks. Turning it into “Given PHP...” adds ceremony without improving the test.
Before writing AC, ask whether the ticket has a clear goal, scope and decisions. Check the ticket with the task readiness tool for open questions. The result is a draft for discussion, not an approval. Use the task readiness checklist for a start check and Definition of Ready vs acceptance criteria to separate the two concepts.