An elaborated requirement tells you what the system must do. It does not tell you what actually happens, step by step, when a person tries to do it, and those are different things.
The gap between them is where a surprising amount of delivery risk lives. A requirement can be completely specified and still leave four people with four different mental models of the sequence. Use cases close that gap by making the sequence explicit.
The short answer to finding the flows a user story leaves unstated: walk each step of the main flow and ask what happens if it fails, if the user is not allowed to continue, if the data changed underneath them, if it times out, or if they give up. Every answer with different system behaviour is an alternate or exception flow, and each one needs an acceptance criterion and at least one test.
Use case vs user story
| User story | Use case | |
|---|---|---|
| Purpose | Captures a need and its value, as a unit of planning | Describes how an actor and the system interact to reach a goal |
| Form | One sentence plus acceptance criteria | Actors, preconditions, trigger, numbered main flow, alternate flows, outcome |
| Strength | Small, prioritisable, conversation-starting | Makes the sequence and its branches explicit |
| Typical gap | The paths it implies but does not state | Can become documentation nobody reads if written for everything |
They are not alternatives. A story says what is needed and why; a use case for the same story shows the steps and every branch, which is where missing acceptance criteria are usually found.
What a use case contains
Generated from the elaborated requirement, each use case carries:
- Primary actor and stakeholders. Who is doing this, and who else has an interest in the outcome.
- Preconditions. What must already be true before the flow can start. This is where unstated assumptions surface.
- Trigger. What starts it, and of what kind.
- Main flow. Numbered steps, each naming an actor and an action. Not prose.
- Alternate flows. The named divergences, each with the condition that causes it and its own steps.
- Outcome. What is true when it finishes.
Each step names its actor explicitly. That sounds like a formality until you read a flow where the actor changes three times and nobody had noticed, which is a common way integration defects get designed in.
Alternate flows are the point
If you only read one section of a generated use case, read the alternate flows.
Many teams distinguish two kinds of branch. An alternate flow still reaches the goal another way; an exception flow ends without it, such as a refused request or a failed payment. ReqLens records both as alternate flows, each with a name, the main-flow step and condition that trigger it, and its own steps; it does not keep a separate exception-flow section.
The main flow is usually already in everyone's head. It is the thing the requirement was written about, the thing the demo will show. It is also the flow least likely to produce a defect, precisely because everyone has thought about it.
Alternate flows are the paths the requirement implied without stating: the payment declines, the session expires mid-flow, the record was deleted by someone else between step two and step five, the user has permission to start but not to finish. Each one is a branch that will exist in the code whether or not anyone specified it. If it is not specified, it gets invented by whoever writes that line.
For each alternate flow, ask whether the system leaves the user somewhere recoverable. A flow that correctly detects a failure and then strands someone with no way forward is a defect that passes every test written against the main flow.
A use case template
Copy this for any requirement with a real sequence in it.
Use case:
Primary actor (whose goal is fulfilled):
Stakeholders (affected, but do not interact):
Preconditions (specific facts true before it starts):
Trigger (user or system initiated, one sentence):
Main flow (3 to 9 numbered steps, each: actor, action):
1.
2.
3.
Alternate flows (name; at which step and under what condition; steps):
Exception flows (name; at which step and under what condition; steps; how the user recovers):
Outcome (what is observably true when it succeeds):
Linked acceptance criteria:
A worked example: refund request flows traced to criteria and tests
These flows were written for this guide, not generated by ReqLens. The acceptance criteria and test case IDs are from the refund requirement's published TestCraft export, used across the ReqLens Academy.
Main flow. Primary actor: customer. Precondition: the customer is signed in and has a delivered order paid by card. Trigger: the customer chooses to request a refund.
- Customer opens the order and requests a refund.
- System checks the order is within the refund window and not already refunded.
- Customer gives a reason and submits.
- System confirms the request to the customer.
- System sends the refund to the original payment card.
Branches, each traced to a criterion and a test:
| Flow | Type | Branches at | Acceptance criterion | Test case |
|---|---|---|---|---|
| Request after the refund window | Exception | Step 2 | ac-1 | TC-013 |
| Order already fully refunded | Exception | Step 2 | ac-3 | TC-003 |
| Refund above the approval threshold goes to an agent | Alternate | Step 4 | ac-4 | TC-004 |
| Customer who did not place the order tries to refund | Exception | Step 1 | ac-7 | TC-007 |
| Payment gateway does not respond | Exception | Step 5 | None yet | None yet |
The last row is the reason to write the flows down. Walking step 5 surfaces a branch the requirement never answered, so it has no criterion and therefore no test. It is the same gap the readiness check flagged for this requirement, and it needs a decision before development starts. See the requirement quality checklist for how to resolve gaps like this one.
Where the model stops and Python starts
Generation is a single Gemini call working from the elaboration. What it does not do is anything deterministic.
Use case identifiers are assigned in Python. Step numbering is normalised in Python. Persistence and routing are Python. The model's job is confined to the semantic work: identifying goals, actors, and the flows that branch off the main one.
This split runs through the whole product, and the reason is consistency. If a model assigns identifiers, they are usually fine and occasionally duplicated or skipped, and you cannot tell which run you got. Deterministic work belongs to deterministic code.
Using them downstream
Use cases are not a documentation deliverable that gets filed after review. They are an input to test design.
A main flow with five steps and three alternate flows is not one test. It is at minimum a test of the main path plus one per branch, and the branches carry the higher information. When test design runs against a requirement that has use cases attached, the flows are available as structure rather than something the test generator has to infer from prose.
Key takeaways
- Use cases make the sequence explicit, which a fully specified requirement still leaves ambiguous.
- Alternate flows are where the value is, because they are the branches nobody wrote down.
- Every step names its actor, which exposes handoffs that would otherwise pass unnoticed.
- Identifiers and step numbering are deterministic Python, not model output.
- Trace every alternate and exception flow to an acceptance criterion and a test; a flow with neither is a gap.
When to generate them
Not for everything. A requirement describing a single field validation does not need a use case, and generating one produces ceremony rather than clarity.
They earn their place when a requirement involves a sequence with more than one actor, a flow that can fail partway, or a process where the order of steps carries rules of its own. If you cannot describe the requirement without using the word "then", it probably warrants a use case. Their alternate flows also make strong test cases: see how to generate test cases from requirements.