GitScrum / Docs
All Best Practices

How to Write Clear Acceptance Criteria | Agile Guide

Write testable acceptance criteria that eliminate rework. Define done before development starts using GIVEN-WHEN-THEN format, PO collaboration, and GitScrum tracking.

9 min read

Clear acceptance criteria align expectations. GitScrum helps track criteria completion and ensures nothing is missed before a story is marked done.

Acceptance Criteria Basics

Purpose

WHY ACCEPTANCE CRITERIA MATTER:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                             β”‚
β”‚ WITHOUT CLEAR CRITERIA:                                     β”‚
β”‚ ───────────────────────                                     β”‚
β”‚ Developer: "I think it's done"                            β”‚
β”‚ PO: "That's not what I meant"                             β”‚
β”‚ Developer: "Back to the drawing board..."                 β”‚
β”‚ β†’ Rework, frustration, delays                             β”‚
β”‚                                                             β”‚
β”‚ WITH CLEAR CRITERIA:                                        β”‚
β”‚ ────────────────────                                        β”‚
β”‚ Developer: "All criteria met and verified"                β”‚
β”‚ PO: "Great, let's ship it"                                β”‚
β”‚ β†’ First-time right, everyone aligned                      β”‚
β”‚                                                             β”‚
β”‚ ─────────────────────────────────────────────────────────── β”‚
β”‚                                                             β”‚
β”‚ ACCEPTANCE CRITERIA DEFINE:                                 β”‚
β”‚ ───────────────────────────                                 β”‚
β”‚                                                             β”‚
β”‚ BOUNDARIES:                                                 β”‚
β”‚ What's in scope, what's not                               β”‚
β”‚ "Password reset via email only (not SMS)"                β”‚
β”‚                                                             β”‚
β”‚ BEHAVIOR:                                                   β”‚
β”‚ How the feature should work                               β”‚
β”‚ "Shows error if email not found"                         β”‚
β”‚                                                             β”‚
β”‚ CONDITIONS:                                                 β”‚
β”‚ Edge cases and special scenarios                          β”‚
β”‚ "Link expires after 24 hours"                            β”‚
β”‚                                                             β”‚
β”‚ MEASURABLE OUTCOMES:                                        β”‚
β”‚ Performance, accessibility                                 β”‚
β”‚ "Page loads in under 2 seconds"                          β”‚
β”‚                                                             β”‚
β”‚ ─────────────────────────────────────────────────────────── β”‚
β”‚                                                             β”‚
β”‚ GOOD CRITERIA ARE:                                          β”‚
β”‚ ──────────────────                                          β”‚
β”‚ βœ… Testable (can verify yes/no)                           β”‚
β”‚ βœ… Clear (no ambiguity)                                   β”‚
β”‚ βœ… Concise (not a novel)                                  β”‚
β”‚ βœ… Independent (can test each one)                        β”‚
β”‚ βœ… Focused on outcome (not implementation)                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Writing Formats

Given-When-Then

GIVEN-WHEN-THEN FORMAT:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                             β”‚
β”‚ STRUCTURE:                                                  β”‚
β”‚ ──────────                                                  β”‚
β”‚ GIVEN [precondition/context]                              β”‚
β”‚ WHEN [action/trigger]                                     β”‚
β”‚ THEN [expected outcome]                                   β”‚
β”‚                                                             β”‚
β”‚ ─────────────────────────────────────────────────────────── β”‚
β”‚                                                             β”‚
β”‚ EXAMPLE: Password Reset                                    β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
β”‚ β”‚ STORY: As a user, I want to reset my password         β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ ACCEPTANCE CRITERIA:                                    β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ 1. GIVEN I am on the login page                       β”‚β”‚
β”‚ β”‚    WHEN I click "Forgot password"                     β”‚β”‚
β”‚ β”‚    THEN I see the password reset form                 β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ 2. GIVEN I entered a registered email                 β”‚β”‚
β”‚ β”‚    WHEN I submit the reset request                    β”‚β”‚
β”‚ β”‚    THEN I receive a reset email within 1 minute       β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ 3. GIVEN I entered an unregistered email              β”‚β”‚
β”‚ β”‚    WHEN I submit the reset request                    β”‚β”‚
β”‚ β”‚    THEN I see "No account with this email"           β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ 4. GIVEN I click the reset link in email              β”‚β”‚
β”‚ β”‚    WHEN I set a new password                          β”‚β”‚
β”‚ β”‚    THEN I can log in with the new password           β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ 5. GIVEN the reset link is over 24 hours old          β”‚β”‚
β”‚ β”‚    WHEN I click the link                              β”‚β”‚
β”‚ β”‚    THEN I see "Link expired, request new reset"      β”‚β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
β”‚                                                             β”‚
β”‚ BENEFITS:                                                   β”‚
β”‚ β€’ Structured and consistent                               β”‚
β”‚ β€’ Easy to convert to automated tests                      β”‚
β”‚ β€’ Clear preconditions                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Checklist Format

CHECKLIST FORMAT:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                             β”‚
β”‚ STRUCTURE:                                                  β”‚
β”‚ ──────────                                                  β”‚
β”‚ Simple list of conditions that must be true               β”‚
β”‚                                                             β”‚
β”‚ ─────────────────────────────────────────────────────────── β”‚
β”‚                                                             β”‚
β”‚ EXAMPLE: User Profile Page                                 β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
β”‚ β”‚ STORY: As a user, I want to view my profile           β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ ACCEPTANCE CRITERIA:                                    β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ ☐ Profile shows name, email, and avatar               β”‚β”‚
β”‚ β”‚ ☐ Avatar displays initials if no image uploaded       β”‚β”‚
β”‚ β”‚ ☐ Edit button visible for own profile only            β”‚β”‚
β”‚ β”‚ ☐ Last login date displayed                           β”‚β”‚
β”‚ β”‚ ☐ Page loads in under 2 seconds                       β”‚β”‚
β”‚ β”‚ ☐ Works on mobile (responsive)                        β”‚β”‚
β”‚ β”‚ ☐ Accessible via keyboard navigation                  β”‚β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
β”‚                                                             β”‚
β”‚ BENEFITS:                                                   β”‚
β”‚ β€’ Quick to write                                           β”‚
β”‚ β€’ Easy to review in demos                                 β”‚
β”‚ β€’ Simple pass/fail verification                           β”‚
β”‚                                                             β”‚
β”‚ ─────────────────────────────────────────────────────────── β”‚
β”‚                                                             β”‚
β”‚ WHEN TO USE WHICH:                                          β”‚
β”‚ ──────────────────                                          β”‚
β”‚                                                             β”‚
β”‚ GIVEN-WHEN-THEN:                                            β”‚
β”‚ β€’ Complex user interactions                               β”‚
β”‚ β€’ Many edge cases                                          β”‚
β”‚ β€’ Will become automated tests                             β”‚
β”‚                                                             β”‚
β”‚ CHECKLIST:                                                  β”‚
β”‚ β€’ Simpler features                                         β”‚
β”‚ β€’ Non-functional requirements                             β”‚
β”‚ β€’ Quick verification needed                               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Common Patterns

Criteria by Type

ACCEPTANCE CRITERIA PATTERNS:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                             β”‚
β”‚ HAPPY PATH:                                                 β”‚
β”‚ ───────────                                                 β”‚
β”‚ The main success scenario                                  β”‚
β”‚ "When user enters valid data, record is created"         β”‚
β”‚                                                             β”‚
β”‚ ERROR HANDLING:                                             β”‚
β”‚ ───────────────                                             β”‚
β”‚ What happens when things go wrong                         β”‚
β”‚ "When email is invalid, show specific error message"     β”‚
β”‚                                                             β”‚
β”‚ EDGE CASES:                                                 β”‚
β”‚ ───────────                                                 β”‚
β”‚ Boundary conditions                                        β”‚
β”‚ "When 0 items in cart, show empty cart message"          β”‚
β”‚ "When 100+ items, show pagination"                       β”‚
β”‚                                                             β”‚
β”‚ PERMISSIONS:                                                β”‚
β”‚ ────────────                                                β”‚
β”‚ Who can do what                                            β”‚
β”‚ "Only admin can delete users"                            β”‚
β”‚ "Users can only edit their own profile"                  β”‚
β”‚                                                             β”‚
β”‚ PERFORMANCE:                                                β”‚
β”‚ ────────────                                                β”‚
β”‚ Speed and scale requirements                               β”‚
β”‚ "Search returns results in under 500ms"                  β”‚
β”‚ "Supports 1000 concurrent users"                         β”‚
β”‚                                                             β”‚
β”‚ ACCESSIBILITY:                                              β”‚
β”‚ ──────────────                                              β”‚
β”‚ Inclusive design requirements                              β”‚
β”‚ "All forms navigable by keyboard"                        β”‚
β”‚ "Images have alt text"                                   β”‚
β”‚                                                             β”‚
β”‚ SECURITY:                                                   β”‚
β”‚ ─────────                                                   β”‚
β”‚ Protection requirements                                    β”‚
β”‚ "Passwords stored hashed, not plaintext"                 β”‚
β”‚ "Session expires after 30 min inactive"                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Complete Example

COMPREHENSIVE STORY WITH AC:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                             β”‚
β”‚ STORY-456: Shopping Cart Checkout                          β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
β”‚ β”‚ AS A customer                                          β”‚β”‚
β”‚ β”‚ I WANT TO complete checkout                           β”‚β”‚
β”‚ β”‚ SO THAT I receive my order                            β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ ═══════════════════════════════════════════════════════ β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ ACCEPTANCE CRITERIA:                                    β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ CART REVIEW:                                             β”‚β”‚
β”‚ β”‚ ☐ Shows all items with name, price, quantity          β”‚β”‚
β”‚ β”‚ ☐ Can modify quantities (1-99)                        β”‚β”‚
β”‚ β”‚ ☐ Can remove items                                     β”‚β”‚
β”‚ β”‚ ☐ Shows subtotal, tax, and total                      β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ SHIPPING:                                                β”‚β”‚
β”‚ β”‚ ☐ Address form validates required fields              β”‚β”‚
β”‚ β”‚ ☐ Postal code validates format                        β”‚β”‚
β”‚ β”‚ ☐ Shows shipping options with prices                  β”‚β”‚
β”‚ β”‚ ☐ Saves address for future orders (opt-in)           β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ PAYMENT:                                                 β”‚β”‚
β”‚ β”‚ ☐ Accepts Visa, Mastercard, Amex                      β”‚β”‚
β”‚ β”‚ ☐ Card number validates with Luhn algorithm           β”‚β”‚
β”‚ β”‚ ☐ CVV required and hidden                             β”‚β”‚
β”‚ β”‚ ☐ Shows card type icon based on number               β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ CONFIRMATION:                                            β”‚β”‚
β”‚ β”‚ GIVEN valid cart, shipping, and payment               β”‚β”‚
β”‚ β”‚ WHEN customer clicks "Place Order"                    β”‚β”‚
β”‚ β”‚ THEN order is created and confirmation shown          β”‚β”‚
β”‚ β”‚ AND confirmation email sent within 1 minute           β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ ERROR HANDLING:                                          β”‚β”‚
β”‚ β”‚ ☐ Payment failure shows "Payment declined"           β”‚β”‚
β”‚ β”‚ ☐ Can retry payment without re-entering details      β”‚β”‚
β”‚ β”‚ ☐ Out of stock items blocked with message            β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ NON-FUNCTIONAL:                                          β”‚β”‚
β”‚ β”‚ ☐ Checkout flow completes in under 3 clicks          β”‚β”‚
β”‚ β”‚ ☐ Works on mobile devices                             β”‚β”‚
β”‚ β”‚ ☐ Page load under 2 seconds                           β”‚β”‚
β”‚ β”‚                                                         β”‚β”‚
β”‚ β”‚ OUT OF SCOPE:                                            β”‚β”‚
β”‚ β”‚ β€’ PayPal (separate story)                             β”‚β”‚
β”‚ β”‚ β€’ Gift cards (separate story)                         β”‚β”‚
β”‚ β”‚ β€’ Multiple shipping addresses                         β”‚β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Common Mistakes

Anti-patterns

ACCEPTANCE CRITERIA ANTI-PATTERNS:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                             β”‚
β”‚ TOO VAGUE:                                                  β”‚
β”‚ ──────────                                                  β”‚
β”‚ ❌ "The form should be user-friendly"                     β”‚
β”‚ ❌ "Performance should be good"                           β”‚
β”‚ ❌ "Handle errors appropriately"                          β”‚
β”‚                                                             β”‚
β”‚ βœ… "Form has inline validation"                           β”‚
β”‚ βœ… "Page loads in under 2 seconds"                        β”‚
β”‚ βœ… "Invalid email shows 'Enter valid email'"             β”‚
β”‚                                                             β”‚
β”‚ ─────────────────────────────────────────────────────────── β”‚
β”‚                                                             β”‚
β”‚ IMPLEMENTATION DETAILS:                                     β”‚
β”‚ ───────────────────────                                     β”‚
β”‚ ❌ "Use React for the frontend"                           β”‚
β”‚ ❌ "Store in PostgreSQL database"                         β”‚
β”‚ ❌ "Use REST API with JSON"                               β”‚
β”‚                                                             β”‚
β”‚ βœ… "Data persists after page refresh"                     β”‚
β”‚ βœ… "API returns response in under 200ms"                 β”‚
β”‚                                                             β”‚
β”‚ ─────────────────────────────────────────────────────────── β”‚
β”‚                                                             β”‚
β”‚ TOO MANY:                                                   β”‚
β”‚ ─────────                                                   β”‚
β”‚ ❌ 25 acceptance criteria for one story                   β”‚
β”‚    (story too big, split it)                              β”‚
β”‚                                                             β”‚
β”‚ βœ… 3-8 criteria per story is typical                      β”‚
β”‚                                                             β”‚
β”‚ ─────────────────────────────────────────────────────────── β”‚
β”‚                                                             β”‚
β”‚ TOO FEW:                                                    β”‚
β”‚ ────────                                                    β”‚
β”‚ ❌ No criteria at all ("we'll figure it out")            β”‚
β”‚ ❌ Only happy path covered                                 β”‚
β”‚                                                             β”‚
β”‚ βœ… Cover happy path + key error cases                     β”‚
β”‚                                                             β”‚
β”‚ ─────────────────────────────────────────────────────────── β”‚
β”‚                                                             β”‚
β”‚ NOT TESTABLE:                                               β”‚
β”‚ ─────────────                                               β”‚
β”‚ ❌ "Users should like the new design"                     β”‚
β”‚ ❌ "System should be scalable"                            β”‚
β”‚                                                             β”‚
β”‚ βœ… "User satisfaction survey scores 4/5+"                 β”‚
β”‚ βœ… "System handles 1000 concurrent requests"              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Related Solutions