Reading a requirement and deriving test cases
The first real skill of manual testing is taking a requirement — often a vague one — and turning it into a set of concrete things to check. Do this poorly and you test only the obvious and miss the bugs; do it well and you cover the cases that matter, systematically, without drowning in an infinite list. This lesson is how to read a requirement and derive good test cases, using a top-up feature as the running example.
Start by understanding what "correct" means
Before writing a single test case, you have to know what should happen — and requirements are often incomplete. Take a requirement like:
"An agent can top up a customer's wallet with an amount."
Read it as a QA and the gaps jump out — and finding these gaps is the first testing you do, at the cheapest possible stage (the cost-curve lesson):
- What is the valid range of "an amount"? Minimum? Maximum? Can it be zero? Negative? Decimals?
- What currency, and how is it formatted (₹, decimals)?
- What if the agent's own float/balance is insufficient?
- What if the customer's wallet does not exist?
- What happens on success — a receipt, a balance update, a notification?
- What happens on failure — the network drops, the server errors, the payment provider times out?
Every one of these is a question whose answer you need to test against, and asking them before development often surfaces requirements nobody had decided. You cannot derive good test cases from a requirement you have not interrogated. So step one is always: understand, and question, what correct means.
Positive, negative, and edge cases
With the behaviour clarified, derive test cases in three deliberate categories — because testing only the first is the classic beginner mistake:
- Positive (happy-path) cases — it does the right thing with valid input. "Top up ₹100 with sufficient float → customer balance increases by ₹100, agent float decreases by ₹100, receipt shown." These confirm it works.
- Negative cases — it correctly rejects or handles invalid input and failures. "Top up ₹0 → rejected with a clear message." "Top up more than the agent's float → rejected." "Network drops mid-request → the agent is told, and no partial top-up happens." Negative cases are where most bugs hide, and where a money app is most dangerous — they are the ones beginners skip.
- Edge / boundary cases — the values at the limits. "Top up exactly the agent's remaining float." "Top up the maximum allowed amount, and one over." "The smallest valid amount, and one under." Bugs cluster at boundaries (the next lesson formalises why).
A useful discipline: for every positive case, ask "what is the negative version?" and "what are the edges?". "Top up ₹100 succeeds" → "top up ₹0 fails", "top up -₹100 fails", "top up ₹1 (min?) ", "top up the max", "top up one over the max". One happy path fans out into a dozen real test cases.
What a test case contains
A test case is a specific, repeatable check. Written down (in a test-management tool or a sheet), it has:
- A title — what it checks, readable: "Top-up rejects an amount above the agent's float".
- Preconditions — the state needed first: "Agent logged in with float of ₹500; customer wallet exists".
- Steps — the exact actions: "1. Enter ₹600. 2. Tap Top up."
- Expected result — what should happen: "Rejected with message 'Insufficient float'; no balance changes." The expected result is the heart — a test case with vague or missing expected results ("check it works") is nearly useless, because a different tester cannot tell pass from fail.
- Test data — the specific values used (the test-data lesson).
The test the "insufficient float" case protects is only meaningful because its expected result is precise — "rejected, this message, no balance change". That last clause is the important one: on a money app, a test case must assert not just the visible message but that money did not move.
Cover the flow, not just the screen
A single feature is usually a flow, not one action, and good test cases cover the flow's paths:
- The main flow end to end (enter amount → confirm → success → balance updated → receipt).
- Alternative flows (agent cancels at the confirm step; agent edits the amount; retries after a failure).
- Error flows (network drops after tapping confirm — did it charge? did it double-charge on retry? these are the money-flow lessons' focus).
- The state around it (what the balance was before and after; what a second top-up does; what happens if two agents top up the same wallet at once).
Testing only the single screen ("the form accepts an amount") misses the flow bugs, which are where the expensive defects live — especially the "network dropped mid-transaction" case, which is exactly where money apps lose or double money.
Do not try to test everything — test what matters
Deriving test cases can generate an infinite list (every combination of every input, device, and network state). You cannot run them all, and trying is a waste (the risk-based-testing lesson). The skill is coverage without exhaustion: use the categories (positive/negative/edge) and techniques (next lesson) to cover each class of behaviour with a representative case, and weight your effort towards the risky and costly parts — the money movement, the failure handling — not another variation of the happy path. Ten well-chosen test cases that cover the positive, negative, edge and error paths of the money flow are worth far more than a hundred that re-check the happy path with different valid amounts. Derive thoroughly, then prioritise — the goal is to cover what matters, not everything.
Check your work
Understand "correct" first. Interrogate the requirement — its gaps (range, currency, insufficient funds, failure behaviour) are bugs found at the cheapest stage. You cannot derive good cases from an un-questioned requirement.
Three categories. Positive (right thing with valid input), negative (correctly rejects/handles invalid input and failures — where bugs hide, and beginners skip), edge/boundary (values at the limits — where bugs cluster). For each positive case, ask the negative and edge versions.
A test case contains. Title, preconditions, steps, and a precise expected result (the heart — vague "check it works" is useless), plus test data. On money apps, assert money did not move on a rejection.
Cover the flow, not the screen. Main, alternative, and error flows, and the surrounding state — the expensive bugs (network-dropped-mid-transaction, double-charge) live in the flows, not a single field.
Cover what matters, not everything. The list is infinite; cover each class with a representative case and weight effort towards the risky/costly parts (money, failure handling), not more happy-path variations.
Practice
- Take the top-up requirement and write down ten questions that expose gaps in it (range, currency, insufficient funds, failure behaviour, success behaviour).
- Derive test cases for it in the three categories — at least three positive, five negative, and the boundary values — for the amount field.
- Write one test case fully (title, preconditions, steps, precise expected result, data) for "top-up rejects an amount above the agent's float", making the expected result assert no balance change.
- Map the top-up flow and write one test case each for the main, an alternative, and an error flow.
- Take a requirement you can find (any app) and find one question whose answer nobody has decided — a bug in the requirement.
- From a set of 30 possible test cases you derive, pick the 10 that matter most and justify the cut by risk/cost.
Official documentation
- ISTQB — Foundation syllabus (test analysis and design) — Deriving test conditions and cases from a basis.
- Ministry of Testing — Test case design resources — Practitioner guidance on writing cases.
- ISTQB — Glossary (test case) — Precise definitions of test case, condition, and expected result.
Next: test design — equivalence partitioning and boundary values.
Stuck on this lesson?
Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.
About the internship