← All posts

Acceptance Criteria Examples Every Agile Team Can Use

Discover practical acceptance criteria examples to help your Agile team define clear user stories and improve project efficiency.

Hands writing acceptance criteria on tablet

Acceptance criteria are the conditions a user story must satisfy before the team marks it done. The fastest way to write one is Given/When/Then (GWT): a three-part sentence that sets a precondition, triggers an action, and states an observable result. Here is a copy-paste example you can drop into a ticket right now:

Given a registered user is on the login page, When they submit a valid email and password, Then they are redirected to the dashboard within 2 seconds and a welcome message is displayed.

That single criterion is testable, measurable, and unambiguous. QA can verify it manually; an automation engineer can map it directly to a Cucumber scenario. For simple UI or configuration checks where there is no state transition, a checklist format works fine: "Password field masks input on entry." But the moment conditional logic or multiple outcomes appear, GWT is the right call.

Key Takeaways

Testable acceptance criteria, written in GWT format with at least one edge-case scenario per story, are the most reliable way to reduce rework and give QA a clear pass/fail signal before a sprint ends.

PointDetails
Use GWT for complex logicGiven/When/Then is required whenever state transitions, conditional logic, or multiple outcomes exist.
Aim for 4–8 criteria per storyCover the happy path, 2–3 error or edge cases, and one non-functional criterion when relevant.
Then must be observableAssert UI messages, HTTP status codes, and redirect URLs — never internal state like database rows or cache keys.
Check DoR before writing criteriaA story that fails INVEST will produce criteria that are wrong; fix the story first.
Treat DoR as a living documentUpdate your DoR checklist whenever the same missing information causes repeated planning delays.

Table of Contents

What acceptance criteria are and how they differ from user stories, test cases, and the Definition of Done

Acceptance criteria are verifiable conditions attached to a single user story. They tell the product owner, QA engineer, and developer exactly what the system must do for the story to be accepted. They are not the story itself, not a test procedure, and not the team's universal Definition of Done (DoD).

Here is how the four artifacts divide responsibility:

  • User story: captures who wants something, what they want, and why ("As a shopper, I want to save items to a wishlist so I can buy them later").
  • Acceptance criteria: state the verifiable conditions that prove the story works ("Given a logged-in shopper, When they click 'Save to Wishlist,' Then the item appears in their wishlist and a confirmation toast is shown").
  • Test case: describes the exact steps, test data, and expected result a tester follows to verify a criterion. It is written after the criterion, not instead of it.
  • Definition of Done: a team-level checklist applied to every story (code reviewed, tests passing, deployed to staging). It is not story-specific.
ArtifactScopeWho writes itLevel of detailWhen evaluated
User storySingle feature intentProduct ownerHigh-levelBacklog refinement
Acceptance criteriaStory-level conditionsPO + QA + devSpecific, verifiableSprint review
Test caseStep-by-step verificationQA engineerDetailed procedureTest execution
Definition of DoneTeam-wide universal checklistScrum teamOrganizationalEnd of every story

The Agile Alliance's acceptance testing glossary describes acceptance tests as formal descriptions of expected behavior, often expressed as examples or usage scenarios rather than detailed test steps. That distinction matters: criteria describe what, test cases describe how.

Pro Tip: Before writing any criteria, confirm the story passes your Definition of Ready (DoR) check. If the business intent is unclear or dependencies are unresolved, the criteria you write will be wrong. Fix the story first.

Which format should you use for acceptance criteria?

Three formats cover nearly every situation. Picking the wrong one wastes QA time and breaks automation pipelines.

Comparison diagram of acceptance criteria formats

Given/When/Then (Gherkin)

GWT is a behavioral-specification template: Given sets the precondition, When triggers the action, Then states the observable outcome. As Martin Fowler's GWT reference notes, the Then clause should focus on user-facing results rather than internal implementation details. Never assert a database row in a Then; assert what the user sees.

Given a guest user is on the checkout page
When they apply an expired discount code
Then an inline error message reads "This code has expired" and the order total is unchanged

GWT is the right choice for state transitions, conditional logic, and any scenario you plan to automate. Behat's scenario-writing guide recommends keeping Given, When, and Then responsibilities distinct, and using Scenario Outlines with example tables for repetitive setups.

Pros: readable by non-technical stakeholders, maps directly to Cucumber/JBehave/Behat, forces observable outcomes. Cons: verbose for trivial checks, can feel over-engineered for a one-line UI rule.

Checklist (verification list)

A checklist criterion is a single pass/fail statement: "The password field masks characters as the user types." No precondition, no action, just a binary check. Use it for simple UI requirements, accessibility rules, and configuration validations where there is no meaningful state transition.

Pros: fast to write, easy to scan, works well for manual QA. Cons: not automation-friendly without extra scaffolding, hides edge cases.

Rule-oriented (business rule / spec)

A rule criterion states a business constraint: "A user may not place more than 10 orders per 24-hour period." This format suits business logic, rate limits, and data validation rules. QA derives test cases from it; automation engineers write parameterized tests against it.

Pros: concise for complex business rules, easy to trace to requirements. Cons: requires QA to infer test scenarios, can become ambiguous without examples.

Tool mapping: GWT/Gherkin maps directly to Cucumber (Java/JavaScript), Behat (PHP), and JBehave. Checklist items work best with manual QA or lightweight assertion libraries. Rule-oriented criteria pair well with unit and integration tests in frameworks like JUnit, pytest, or RSpec, and with Selenium for UI-level validation.

How to write testable acceptance criteria step by step

Follow this sequence during backlog refinement. It takes about 10 minutes per story when the team is aligned.

  1. Start with the user story. Read the story aloud. Confirm the who, what, and why are clear. If they are not, stop and fix the story before writing criteria.
  2. Check your Definition of Ready. Per Atlassian's DoR guidance, a story is ready when it is independent, negotiable, valuable, estimable, small, and testable (INVEST). Acceptance criteria cannot be written for a story that fails INVEST.
  3. Pick your format. State transition or conditional logic? Use GWT. Simple UI check? Use a checklist. Business rule? Use rule-oriented.
  4. List preconditions. What system state must exist before the action? A logged-in user, an empty cart, a specific role.
  5. State the action. One action per criterion. "When they click Submit" not "When they fill out the form and click Submit and the server responds."
  6. Write the observable outcome. What does the user see, receive, or experience? HTTP status, UI message, redirect, email, error text.
  7. Add at least one negative/edge-case criterion. What happens when input is invalid, the network is slow, or a limit is exceeded?
  8. Aim for 4–8 criteria per story. Cover the happy path, 2–3 error or edge cases, and one non-functional criterion (performance or SLA) when relevant.

Before accepting a story into a sprint, confirm:

  • Business intent is documented and agreed upon by PO and dev
  • Dependencies on other stories or external services are identified
  • Acceptance criteria are written and reviewed by at least one QA engineer
  • The story is small enough to complete within a single sprint
  • No open design or UX decisions remain unresolved

Rewriting vague criteria:

VagueTestable
"The page loads quickly""The dashboard loads within 2 seconds on a 4G connection (Lighthouse performance score ≥ 90)"
"Users should see an error""Given an invalid email format, When the user submits the form, Then an inline error reads 'Enter a valid email address'"
"The API should handle errors""Given a missing required field, When the endpoint receives the request, Then it returns HTTP 422 with a JSON body containing an 'errors' array"

Five common mistakes in acceptance criteria

1. Vague outcomes

"The system should respond appropriately" tells QA nothing. Every criterion needs a specific, observable result: a status code, a message string, a redirect URL, a time threshold.

Bad: "The login should work correctly." Fixed: "Given valid credentials, When the user submits the login form, Then they are redirected to /dashboard within 2 seconds."

2. Implementation details in the Then clause

"Then the users table is updated with a last_login timestamp" is a database assertion, not a user-observable outcome. QA cannot verify this without database access, and it couples the test to the implementation.

Bad: "Then the Redis cache is invalidated." Fixed: "Then the user's profile page reflects the updated display name immediately."

3. Untestable language

Words like "user-friendly," "intuitive," "fast," and "secure" are not testable. Replace them with measurable thresholds or observable behaviors.

Bad: "The checkout flow should be user-friendly." Fixed: "A first-time user can complete checkout in under 3 minutes without accessing help documentation."

4. Missing edge cases

A criterion that covers only the happy path leaves QA guessing about error handling. Every story needs at least one negative scenario: invalid input, expired session, network failure, or permission denied.

Hands placing tokens representing edge cases

Bad: Only "Given a valid coupon code, When applied, Then the discount is shown." Fixed: Add "Given an expired coupon code, When applied, Then an error reads 'This code has expired' and the total is unchanged."

5. Acceptance criteria that duplicate the Definition of Done

"Code must be reviewed and merged" belongs in the DoD, not in story-level criteria. Duplicating DoD items in criteria creates confusion about where the standard lives and who enforces it.

Red-flag checklist for refinement:

  • Does any criterion say "should be" instead of specifying an observable result?
  • Does any Then clause reference a database, cache, or internal service?
  • Does any criterion use unmeasurable adjectives (fast, secure, intuitive)?
  • Is there at least one error or edge-case criterion?
  • Do any criteria restate items already in the team's DoD?

20 production-ready acceptance criteria examples across five domains

The Spec Coding acceptance criteria guide makes the case that production-grade examples must include edge cases, observable outcomes, and timing or SLA constraints. The examples below follow that standard. Each block is copy-paste ready for a Jira ticket or GitHub issue.

Authentication (4 examples)

Story: As a registered user, I want to log in with my email and password.

  • Happy path: Given a registered user with valid credentials, When they submit the login form, Then they are redirected to /dashboard within 2 seconds and a session cookie is set.
  • Wrong password: Given a registered user, When they submit an incorrect password, Then an error reads "Invalid email or password" and no session is created.
  • Account lockout: Given a user who has failed login 5 times, When they attempt a 6th login, Then the account is locked for 15 minutes and an email notification is sent.
  • Edge case (SQL injection): Given a user who enters ' OR '1'='1 in the email field, When they submit the form, Then the system returns "Invalid email or password" and logs the attempt.

E-commerce (4 examples)

Story: As a shopper, I want to apply a discount code at checkout.

  • Valid code: Given a shopper with items in their cart, When they apply a valid 10% discount code, Then the order total decreases by 10% and the applied code is displayed.
  • Expired code: Given a shopper, When they apply an expired code, Then an inline error reads "This code has expired" and the total is unchanged.
  • Already-used code (single-use): Given a code limited to one use per account, When the same user applies it a second time, Then an error reads "You have already used this code."
  • Edge case (empty cart): Given a shopper with an empty cart, When they apply any discount code, Then an error reads "Add items to your cart before applying a discount."

APIs (4 examples)

Story: As a developer, I want the Orders API to validate required fields.

  • Valid request: Given a POST to /orders with all required fields, When the request is received, Then the API returns HTTP 201 with the new order ID in the response body.
  • Missing field: Given a POST to /orders with the customer_id field absent, When the request is received, Then the API returns HTTP 422 with a JSON body: {"errors": ["customer_id is required"]}.
  • Unauthorized: Given a request with an invalid or missing Bearer token, When the endpoint is called, Then the API returns HTTP 401 and no order is created.
  • Edge case (rate limit): Given a client that sends more than 100 requests per minute, When the limit is exceeded, Then the API returns HTTP 429 with a Retry-After header.

For authentication-related API criteria, teams building security-sensitive features can cross-reference organizational standards in the SwarmStack security guidelines.

Data processing (4 examples)

Story: As an analyst, I want uploaded CSV files to be processed and stored.

  • Valid upload: Given a CSV with valid headers and fewer than 10,000 rows, When the file is uploaded, Then processing completes within 60 seconds and a success notification is displayed.
  • Invalid format: Given a file with an unsupported extension (.xlsx), When uploaded, Then the system rejects it with "Only CSV files are supported."
  • Oversized file: Given a CSV exceeding 50 MB, When uploaded, Then the system returns an error before processing begins: "File size exceeds the 50 MB limit."
  • Edge case (duplicate rows): Given a CSV containing duplicate primary keys, When processed, Then duplicates are skipped and the summary report shows a count of skipped rows.

Notifications (4 examples)

Story: As a user, I want to receive an email confirmation after placing an order.

  • Happy path: Given a completed order, When the order is confirmed, Then a confirmation email is delivered to the user's registered address within 60 seconds.
  • Invalid email on file: Given a user whose email address is malformed, When an order is placed, Then the system logs a delivery failure and flags the account for review.
  • Opt-out: Given a user who has unsubscribed from transactional emails, When an order is placed, Then no email is sent and the preference is preserved.
  • Edge case (retry on failure): Given a transient SMTP failure, When the first delivery attempt fails, Then the system retries up to 3 times at 5-minute intervals before logging a permanent failure.

Covering edge cases like these also reduces project risk by surfacing failure modes before they reach production.

Blank templates and issue-tracker snippets

GWT template (copy into any ticket)

**User story:** As a [role], I want [feature] so that [benefit].

**Acceptance criteria:**

**Scenario 1 — [Happy path label]**
Given [precondition]
When [action]
Then [observable outcome]

**Scenario 2 — [Error/edge case label]**
Given [precondition]
When [action]
Then [observable outcome]

**Non-functional criterion (if applicable):**
[Feature] must [measurable threshold, e.g., respond within X seconds under Y concurrent users].

Checklist template (copy into any ticket)

**Acceptance criteria:**
- [ ] [Observable behavior 1]
- [ ] [Observable behavior 2]
- [ ] [Error state: what the user sees when X fails]
- [ ] [Non-functional: performance, accessibility, or security threshold]

Jira/Confluence field conventions

Store criteria in a dedicated Acceptance Criteria field, not in the description. Add a Preconditions field for shared setup (e.g., "User must be logged in as Admin"). Use a Test Notes field for QA-specific hints that do not belong in the criterion itself.

For GitHub issues, add a criteria block under a ## Acceptance Criteria heading and use task-list syntax (- [ ]) so engineers can check off items as they verify them. The Microsoft Code With Engineering Playbook recommends treating your DoR as a living checklist stored directly in issue templates, updating it whenever the same missing information causes repeated planning friction.

Pro Tip: Add a short [AC-ID] tag to each criterion (e.g., [AC-01]) so automation engineers can reference specific criteria in test method names. This creates a traceable link between the ticket and the test suite without any extra tooling.

Turning acceptance criteria into acceptance tests and automation

A GWT criterion maps almost directly to a Cucumber feature file. The Given block becomes the test setup (or a Background if shared across scenarios), the When block triggers the action, and the Then block holds the assertion. Wikipedia's GWT article notes that GWT scenarios can be automated as browser tests with tools like Selenium and Cucumber, functioning as both a communication and automation bridge.

Mapping patterns:

  • GWT scenario → Cucumber/Behat/JBehave feature file scenario
  • Checklist item → single assert or expect statement in a unit or integration test
  • Rule-oriented criterion → parameterized test with multiple input/output pairs (Scenario Outline in Gherkin)

Automation best practices:

  • Assert HTTP status codes, response schema, and UI-visible text. Never assert database rows or internal cache state directly.
  • Keep Then clauses to one observable outcome per scenario. Multiple assertions in one Then blur failure diagnosis.
  • Use Scenario Outlines and example tables for repetitive setups rather than duplicating full scenarios.
  • Prefer CSS selectors tied to data-testid attributes over XPath or text-based selectors to reduce flakiness.

Flakiness reduction checklist:

  • Then clause asserts only user-visible state (UI message, HTTP response, redirect URL)
  • No hard-coded sleep or wait; use explicit waits tied to element visibility
  • Test data is isolated per scenario (no shared mutable state between tests)
  • External dependencies (email, SMS, third-party APIs) are mocked or stubbed in unit/integration tests

What to avoid:

DoDon't
Assert HTTP 422 and error message bodyAssert that a specific database column was updated
Assert UI toast text after form submissionAssert that a Redux store action was dispatched
Assert redirect URL after loginAssert that a specific function was called internally

How Definition of Ready and Definition of Done relate to acceptance criteria

DoR and DoD are complementary guardrails, and neither replaces story-level acceptance criteria. The Atlassian DoR guide describes DoR as a checklist ensuring backlog items are actionable and testable before the team starts work, commonly referencing INVEST characteristics. DoD is the organization-wide standard applied when work is complete.

DoR checklist for acceptance-criteria readiness:

  • Business intent is documented and agreed upon by the product owner
  • Dependencies on other stories or external systems are identified
  • Acceptance criteria are written and cover at least one happy path and one error case
  • Criteria are reviewed by at least one QA engineer and one developer
  • The story is small enough to complete in one sprint
  • No open UX or design decisions remain

Where each artifact is evaluated:

  • Refinement: write acceptance criteria, check DoR
  • Sprint planning: confirm DoR is met before pulling the story into the sprint
  • Sprint review: verify acceptance criteria are satisfied; apply DoD before closing

Sample workflow:

  1. PO adds a story to the backlog with a user story and rough notes.
  2. Team refines the story: PO clarifies intent, QA drafts GWT criteria, dev flags dependencies.
  3. DoR check: all items above are confirmed.
  4. Story enters the sprint. Dev implements against the criteria.
  5. QA verifies each criterion. Automated tests run in CI.
  6. DoD is applied: code reviewed, tests green, deployed to staging, documentation updated.
  7. PO accepts the story at sprint review.

Acceptance criteria live at step 2 and are verified at step 5. DoD lives at step 6. Conflating them creates ambiguity about who owns what and when.

What stronger acceptance criteria actually save you

Teams that invest 10 minutes writing precise criteria during refinement consistently recover that time in QA cycles. The pattern is predictable: a vague criterion ("the form should validate correctly") generates a round of back-and-forth between QA and dev after the story is built. A precise criterion ("Given an email field left blank, When the form is submitted, Then an inline error reads 'Email is required' and focus returns to the email field") eliminates that conversation entirely.

The edge-case criterion is where most teams underinvest. Adding one error-path scenario per story is the single highest-leverage habit a team can build. It forces the product owner to make a decision about failure behavior during refinement, when changing the design costs nothing, rather than during QA, when it costs a sprint.

One practical habit worth adopting: at the end of every refinement session, ask "What happens when this fails?" for each story. If nobody can answer, the story is not ready. That question alone surfaces missing edge cases faster than any checklist.

Sources

The sources below cover the theory, tooling, and practical templates referenced throughout this article.


Looking for a faster way to align your team on requirements before writing acceptance criteria? SwarmStack runs structured, AI-driven planning sessions where product owners, engineers, and QA can define story intent, surface edge cases, and produce versioned deliverables in one session. Teams export directly to Jira or GitHub, so criteria land in the right ticket from the start.

Swarm-stack