Acceptance Criteria

By the Syncfusion DevTutorials team · Last updated

Write acceptance criteria as Given, when, then checks that a runner can execute. Prove they work by catching three planted bugs while the correct build passes. Then download your v1 spec kit: intent.md and spec.md for your tool.

"Done", With Nothing to Prove It

Remember Run 4 in the Guess Gallery?

The agent followed every requirement. It built the feature. It ran a small test. Then it said:

Done.

But there was still a bug in the result.

Nothing noticed it, because nothing checked the result properly.

This is a verification gap.

Verification Gap = the work looks finished, but nothing proves it is right.

Simple lesson: "done" is only a word until a check proves it.

A Real-World Example

You order a cake for 12 people.

"The cake is nice" is not a check. Every baker says their cake is nice.

"There are 12 slices" is a check. You can count them.

Acceptance criteria are checks like that, for software.

Done, with nothing to prove it

Click the button and open the Agent tab.

  • The requirements: there are three, and they are good.
  • The acceptance criterion: there is only one, "the export works correctly". The lab marks it NOT EXECUTABLE.
  • The builds: the lab tries three builds, each with a planted bug. All three survive.

The requirements were not the problem.

The problem is that nothing could check the result.

Simple lesson: requirements say what to build. Acceptance criteria prove it was built right.

TL;DR

  1. Acceptance criterion (AC) = a check that proves a requirement was built correctly.
  2. Write each one as Given, when, then:

    • Given = the starting state.
    • When = the action.
    • Then = the result you can see.
  3. The Then must be something a check can see, such as:

    • a number of rows
    • a date format
    • a button
    • a status code
  4. "It works" or "the export is correct" cannot be checked.
  5. A good check passes the correct build and fails a buggy build.
  6. Mutation testing = planting bugs on purpose to see if your checks catch them.
  7. At the end of this lesson, you download your v1 spec kit: intent.md and spec.md.

What You Will Learn

In this lesson, you will learn:

  1. What an acceptance criterion is.
  2. How it is different from a requirement.
  3. How to write one with Given, when, then.
  4. What makes a Then something a check can see.
  5. How planted bugs prove your checks work.
  6. How to export your first spec kit for your tool.

About the builds in this lab

  • There are four simulated builds.
  • One build is correct.
  • Three builds each have one planted bug.
  • Your checks run against all four, using fixed rules. No AI grades anything.

What an Acceptance Criterion Is

A good set of acceptance criteria passes the correct build and catches every planted bug.

Requirement vs Acceptance Criterion

Requirement = what to build.

Example:

When the user clicks Export, the grid shall export only the rows shown by the current filter.

Acceptance criterion = how to check it was built right.

Example:

Given a filter that shows 2 rows, when the user clicks Export, then the file has 2 data rows.

You need both.

  • The requirement removes a guess before the work starts.
  • The acceptance criterion proves the result after the work is done.

Simple lesson: a requirement without a check is a promise nobody tests.

Given, When, Then

Every acceptance criterion has three parts:

  • Given = the starting state.
  • When = the action.
  • Then = the result you expect to see.

Example:

  • Given: a filter that shows 2 rows.
  • When: the user clicks Export.
  • Then: the file has 2 data rows.

In the lab, start each line with an ID like AC-1:.

The runner uses the ID when it shows the results.

If a line does not have all three parts, the runner cannot use it. The lab shows NOT EXECUTABLE and tells you why.

Make the Then Something a Check Can See

Something a Check Can See

Most weak acceptance criteria go wrong in the Then.

A check can see these:

  • "the file has 2 data rows"
  • "the Created cell is 2026-10-01"
  • "an error message with a Retry button is shown"
  • "the response is 503 with a Retry-After header"

A check cannot see these:

  • "it works"
  • "the export is correct"
  • "the user is happy"

A check can count rows. It can read a value. It can find a button or a status code.

But it cannot tell if something "works". That word means different things to different people.

Simple lesson: if a robot could not answer yes or no, rewrite the Then.

The Given Must Set Up the Then

The Given must create the situation the Then talks about.

Example:

Given a normal day,
when the user clicks Export,
then a Retry button is shown.

This check is wrong. Nothing failed, so there is no reason for a Retry button.

Another example:

Given some data,
when the user clicks Export,
then the file has 2 rows.

This check is not finished. The Given does not say how many rows the filter shows.

Watch one check get better, step by step:

The check only works once the Given and the Then agree.

Important: a check that fails on the correct build is a broken test.

If the Given says 2 rows, the Then must expect 2 rows.

Prove Your Checks With Planted Bugs

Mutation Testing

How do you know your checks are good?

Try them on builds that you know are wrong.

The lab has four builds:

  1. The correct build.
  2. A build that ignores the filter.
  3. A build that writes dates in the wrong format.
  4. A build with no Retry action.

Two words to know:

  • Caught = at least one check fails on the buggy build.
  • Survives = every check passes, so the bug gets through.

Mutation testing = planting small bugs on purpose to see if your checks notice them.

Watch what happens as checks are added, one at a time:

Each check catches one bug. You need one check for each requirement.

Simple lesson: a set of checks is only as good as the bugs it catches.

Lab Exercise: Catch All Three Planted Bugs

Open the spec. Replace this line:

the export works correctly

Write checks for every requirement, so that every planted bug is caught.

Catch all three planted bugs

Press Check my spec, then open Preview & Checks.

A table shows each check against each build.

You pass when:

  • the correct build passes every check;
  • every buggy build is caught.

Start with one check per requirement.

This spec has three requirements:

  • the filtered rows
  • the date format
  • the Retry after a failure

Your v1 Spec Kit

What Is in the Kit

You now have two files:

  • intent.md from the Problem Statements lesson
  • spec.md from this lesson

Together, they say what to build and how to check it.

The export puts the files where your tool expects them:

ToolMain fileAlso adds
Claude Codedocs/specs/excel-export/intent.mdCLAUDE.md
Spec Kitspecs/001-excel-export/spec.md.specify/memory/constitution.md
Kiro.kiro/specs/excel-export/requirements.md.kiro/steering/product.md

It also adds a line to files like AGENTS.md or CLAUDE.md. That line tells the agent to read the spec before it decides anything.

Spec Kit and Kiro do not use a separate intent file. For those tools, your intent goes inside the spec file.

The zip also holds extra files, such as templates, a plan and review tools.

Lab Exercise: Download Your v1 Spec Kit

Open the Export tab and choose your tool.

Both files must pass their checks before the download is ready.

Download your v1 spec kit

If intent.md is not finished, go back to the Problem Statements lesson first.

When every check passes, download the zip file.

The README inside has prompts you can try in your tool.

What Changes per Tool

ToolWhere ACs live
Claude Code, Codex, Cursorunder Acceptance criteria in docs/specs/<feature>/spec.md
Spec Kitacceptance scenarios under each user story in specs/<NNN-feature>/spec.md
Kiroacceptance criteria under each requirement in .kiro/specs/<feature>/requirements.md

Given, when, then works the same way in every tool.

Only the place where the checks are kept is different.

Common Mistakes

MistakeWrong ideaCorrect ideaWhat goes wrong
Writing "the export works correctly"It sounds like a check."Then the file has 2 data rows."Nothing can run it, so every bug gets through.
A Then that does not match the Given"A stricter check is better."Given 2 rows, then 2 rows.The correct build fails, so the test is broken.
Checking Retry when nothing failed"Just check that the Retry button exists."Given the export fails, then a Retry button is shown.The Retry never shows, so it is never checked.
One check for everything"One good check is enough."One check for each requirement.Bugs in the other requirements get through.
Trusting the agent's own test"It said tested and done."Write your own checks, from the stakeholder's view.The agent's test only checks what it built.
Never testing your checks"They look right."Run them against planted bugs.A hole in your checks stays hidden.

Exercises

These exercises help you practise writing checks that really work.

Press Check when you are ready. Use Show Hint if you get stuck.

What to Remember

  • Requirements say what to build.
  • Acceptance criteria prove it was built right.
  • Write every check as Given, when, then.
  • The Then must be something a check can see.
  • The Given must set up the situation the Then talks about.
  • Good checks pass the correct build and catch the planted bugs.
  • Your v1 spec kit holds intent.md and spec.md, ready for your tool.

Further Reading

Next: API Contracts. You will learn how a clear contract stops the agent from inventing function names.