Examples and Acceptance Criteria
"Full refund up to 12 hours before the class" reads clearly until you ask about 11 hours 59 minutes, exactly 12 hours and a booking made last month. Concrete inputs with expected outputs settle what the sentence left open, and they give the agent a specification it can check its own work against.
They are also tests waiting to be written. That makes this page the step from specifying a task to Chapter 8, where the tests become the contract.
Rules Hide Boundaries
"Up to 12 hours" does not say what happens at exactly 12 hours before the class. Read one way, "up to" includes the 12th hour; read another, it stops just short of it. Ines decides: "up to" is inclusive, so a cancellation exactly 12 hours ahead gets the full refund.
Until someone decides, the boundary is a coin the agent tosses for you. It will write a comparison that either includes the boundary or excludes it, the two only a character or a word apart in the code, and either choice compiles, passes any test that does not sit exactly on the line, and looks deliberate in the diff. Chapter 6 shows the agent making that choice on its own and making it the wrong way.
The Example Table
For a class starting at 18:00 on the gym's clock: a cancellation at 05:59 the same day, 12 hours and 1 minute ahead, gets a full refund. At 06:00, exactly 12 hours ahead, a full refund, by Ines's ruling. At 06:01, 11 hours and 59 minutes ahead, nothing. A booking made a month before the change and cancelled at 05:00, 13 hours ahead, gets a full refund, because the rule follows the cancellation time and not the booking date. And a cancellation at 17:00, one hour ahead, gets nothing, as it does today: late cancellations get no refund, and this task does not change that.
| Given | When the member cancels at | Then | Under the old 24-hour rule |
|---|---|---|---|
| A class at 18:00 | 05:59 (12 h 1 min before) | Full refund | No refund: changes |
| A class at 18:00 | 06:00 (exactly 12 h before) | Full refund | No refund: changes |
| A class at 18:00 | 06:01 (11 h 59 min before) | No refund | No refund |
| A class at 18:00, booked a month before the change | 05:00 (13 h before) | Full refund | No refund: changes |
| A class at 18:00 | 17:00 (1 h before) | No refund | No refund |
Five rows, and three of them change the outcome members see today. Those three are the rows a reviewer will look for first, and the 06:00 row is the one the sentence alone never settled.
Each row earns its place. The 05:59 and 06:01 rows sit a minute either side of the line, and the 06:00 row sits on it; together they settle the boundary. The month-old booking is there because Ines's ruling about existing bookings is a rule of its own, and a rule without a row is a rule nobody will test. The 17:00 row is the ordinary late cancellation, the case the task does not change, kept so that a diff which accidentally refunds late cancellations has a test to fail.
Examples as the Specification the Agent Checks
Put the table in the task (the first topic of this chapter) and require one test per row. The agent then has a "done" it can run, row by row, before it stops. You get a checklist for review: is there a test for each row, and does each test assert the table's output, a literal "full refund" at 06:00, rather than whatever the code happens to return? A test that copies the current behaviour into its expected value proves nothing, and Chapter 8 shows how to spot one.
Examples Find the Questions
Writing the table is when you find out what the sentence left open. Is exactly 12 hours inside or outside? Do the 12 hours count on the gym's clock or the server's, given that Cragmoor's four gyms sit in two time zones an hour apart (Chapter 8)? What does a booking made before the change get? Each question goes to Ines before the agent starts, not after the diff arrives, because a boundary settled inside a diff is settled by whatever the agent's code happens to do.
The time-zone question is a good example of a row the first draft of the table did not have. Cragmoor's timetable is written on each gym's own clock, so "18:00" means 18:00 where the class is. Asked, Ines confirms that the 12 hours count on that same clock: a member at a gym in the second time zone has until 06:00 on their clock, not the server's. That answer belongs in the task as a sentence and in the table as a row for a gym in the second zone. The refund task went out with neither, and Chapter 6 shows what the agent did to the deadline code without them.
Acceptance Criteria
Acceptance criteria are the team-level form of the same thing: statements of observable behaviour a product owner agrees to, such as "a member who cancels 12 hours or more before the class sees 'full refund' and receives it". Back each criterion with at least one example row, because a criterion without a concrete case still hides its boundary. QA & Software Testing for Beginners covers acceptance criteria in its chapter on how software gets built, and the technique behind the choice of rows, boundary value analysis, in its chapter on test design.
The Step to Chapter 8
Every row becomes a test, ideally written or approved by you before the code changes. The agent then works against a contract it cannot reinterpret, and a green run means the table holds. Chapter 8 runs the refund change that way for the three rows at the line and shows what they catch that review alone missed.
Put the table where the agent will read it: in the task file, or in the ticket the task points at, as plain rows that a person can check at a glance. A table hidden in a spreadsheet the agent cannot reach is a table it will not use, and a table that exists only in your head is the sentence again, with all its boundaries still open.
Acceptance criteria state the behaviour in words a non-engineer can agree to.
Examples pin that behaviour to concrete inputs and outputs, boundaries included. Tests make the examples executable. Write them in that order: the agent can turn examples into tests, but it cannot decide where the business draws a boundary.
- "The rule is clear, so examples are redundant." The rule is clear until 12 hours exactly. Every rule with a threshold has a boundary its sentence does not settle.
- "The agent will think of the edge cases." It thinks of the edges the code's shape suggests, such as an empty input or a missing value. Edges from the domain, such as the gym's time zone or a cancellation exactly at the threshold, come from someone who knows the business.
- "Examples belong in the tests, not in the task." In the task they steer the work and define done; in the tests they enforce it. They belong in both.
- "Acceptance criteria are the product owner's job." Someone has to turn them into rows with numbers, and the engineer who skips that step hands the boundary decisions to the agent.
- "Three examples are enough." Enough is one on each side of every boundary, one at it, one per exception and one ordinary case. Count the edges, not the rows.
- Write a row on each side of every boundary and one on it: 11 hours 59 minutes, 12 hours and 12 hours 1 minute, not only "well before" and "well after".
- Put the example table in the task and require one test per row. The agent gets a done it can run, and you get a review checklist.
- Take every question the table raises to whoever owns the rule before the agent starts. A boundary settled inside a diff is settled by accident.
- Check that each test asserts the table's output, not the code's. A test copied from current behaviour proves nothing.
Knowledge Check
The rule is "full refund up to 12 hours before the class". Which set of examples covers its boundary?
- Cancellations 2 days before and 1 hour before the class starts
- Cancellations 12 h 1 min, exactly 12 h and 11 h 59 min before
- Cancellations 24 hours and 12 hours before the class starts
- Cancellations 6, 12 and 18 hours before the class starts
The task says "up to 12 hours" and nothing else about the boundary. What happens at exactly 12 hours?
- The agent stops and asks, because the boundary is ambiguous
- The test runner flags the ambiguity when it runs the suite
- The agent picks
<=or<, and that choice is the policy - The language's date library decides it the same way everywhere
A test for the 06:00 row computes its expected value by calling the refund function. What is wrong with it?
- It asserts whatever the code returns, so it passes whether the code is right or wrong
- It calls the refund function, which tests are not supposed to do in this codebase
- It uses 06:00, which is too close to the boundary to give a stable result in tests
- It should test 06:01 instead, since 06:00 is covered by Ines's inclusive ruling
What is the difference between an acceptance criterion and an example?
- An acceptance criterion is written by the engineers, and an example by the product owner
- An example describes the code, and an acceptance criterion describes the user interface only
- An acceptance criterion is executable, and an example is only documentation for the people
- The criterion states behaviour in words; the example pins it to concrete inputs and outputs
You got correct