The Oracle Is Usually Already Written Down
The expected results for a discount-gating story were already enumerated in a sibling story under the same epic — including a struck-out line that handed over an entire negative case.
Writing the steps is the easy half. Deciding what the correct answer is takes longer than everything else combined.
That decision is where a tester quietly parts company with the specification. Steps are mechanical. The expected result is a judgement, and every judgement is a chance to be confidently wrong in a document that other people will trust.
On one story that judgement took me most of a morning. The answer was already written down, in full, three tickets away.
The Story Under Test Doesn't Restate What It Gates
The story was a gate. Which discount changes trigger contractual documents, and which ones don't.
Read on its own, it said what should happen when the gate fires. It did not say which changes were on which side of the gate. So the natural move is to reason it out: a discount changes the price, the price is contractual, therefore documents. Reasonable. Also unverified, and about to become the expected result on a dozen test cases.
The list I was trying to derive existed. It sat in a sibling story under the same epic, written earlier, when someone had to enumerate the behaviour for the first time.
Two Lines, One of Them Crossed Out
The sibling story carried the trigger list verbatim. Changing the broadband discount was on it. Adding a fixed-IP add-on was on it too — struck through.
That is the whole oracle, and it hands over two scenarios for free.
A bundle-level discount change triggers the documents. An add-on addition does not. Positive case and negative case, both authoritative, neither invented by me. The struck-out line is worth more than the live one, because a negative expected result is exactly the thing a tester never has the confidence to assert alone.
Compare that to what I would have written from first principles. Documents on any price-affecting change — which would have made the add-on scenario a defect. I would have raised it, someone would have closed it as working-as-designed, and the whole exchange would have been caused by a list I never read.
Why the Authoritative List Lives Somewhere Else
A story that gates, overrides or suppresses existing behaviour is written for a reader who is assumed to already know the behaviour.
The author of that story is not documenting the system. They are documenting a delta. Restating the base behaviour feels redundant to them, and by their standards it is — they wrote the base behaviour six weeks earlier, in the story that established it.
So the what-fires-when list belongs to the requirement family, not to any single member of it. The epic is the unit of meaning. The story is a unit of delivery, and those are not the same shape.
A tester who reads only the story under test is not reading half the requirement. They are reading a delta as if it were an absolute, which is worse than reading nothing, because it produces a complete, plausible, internally consistent oracle that disagrees with the spec.
What to Do Before You Write a Single Expected Result
For any story whose verbs are gate, override, suppress, restrict, or block, spend ten minutes on the family before you spend an hour on the oracle.
- Open the epic and list every sibling story, including the closed ones. The behaviour being gated was almost certainly delivered by one of them, and closed stories are the ones nobody rereads.
- Search the siblings for enumerations, not prose. Trigger lists, tables, bullet lists of conditions. Those are the artefacts written at the moment someone was forced to be exhaustive, and they are the only places where a negative case appears in writing.
- Read the struck-out and edited lines as content, not as noise. A crossed-out entry in a requirement is a decision someone made and then recorded. It is the cheapest negative test case you will ever be handed.
If the family genuinely does not contain the list, that is a finding in itself, and it belongs in your open questions rather than in your expected results.
The Cheapest Review Nobody Runs
There is a second habit that attacks the same problem from the other end, and it costs one analyst-hour.
Take a requirement that has already been analysed. Have a second person analyse it without reading the first analysis. Not a review — a blind re-derivation from the raw requirement.
We did that on a discount-flexibility requirement. The second pass surfaced three material questions the first one had not asked. When does a percentage discount get converted to an absolute amount — at the moment it is applied, or at sync to the billing system, which matters enormously if the cart price changes in between? Which price is the ceiling when validating that an absolute discount exceeds the product price — list price, promotion-adjusted price, or the per-period recurring charge? And does a manual discount stack with promotion discounts already sitting in the cart, or replace them?
None of those are exotic. All three are places where the requirement is simply silent, and silence is invisible to the person who has already filled it in.
Compare the Open Questions, Nothing Else
Here is the part worth sitting with. The valuable output of that exercise is not either analysis. It is the difference between the two Open Questions sections.
A reviewer who reads the existing analysis inherits its assumptions. They cannot help it — the document explains the requirement to them, and an explanation that resolves an ambiguity also hides it. A blind pass has no such anchor, so it diverges from the first one at exactly the points where the requirement failed to decide something.
Every question that appears in one analysis and not the other marks an assumption somebody made without noticing they were making it. That is the whole diff you need to read, and it takes minutes.
The first analyst cannot see their own blind spots, because they already know the requirement. Knowing it is the problem.
Before you write your next set of expected results — do you know whether they already exist somewhere in the epic?