TransitLink: Boundary Values, Workflow States and a Coverage Claim
TransitLink sells rail tickets. On the booking form, the 'age' field accepts an integer from 18 to 65 inclusive for the adult fare; 2–17 is a child fare requiring a guardian flag; 0–1 is an infant. The developer wrote four tests for the adult fare: ages 18, 65, 30 and 17. The order workflow is a state machine: DRAFT→SUBMITTED→APPROVED→SHIPPED, SUBMITTED→REJECTED, REJECTED→DRAFT, and APPROVED→CANCELLED. Six hand-written workflow tests exist. The CI coverage report claims 100% statement coverage but only 68% branch coverage. The team lead argues this proves the workflow is thoroughly tested and that no further tests are needed before release.
1. Apply equivalence partitioning and boundary value analysis to the age field. What is wrong with the four existing tests?
Read the worked answer
Equivalence partitions (the field drives three rules, so partition across all of them):
- age < 0, non-integer, blank, text - invalid input partitions
- 0–1 infant
- 2–17 child (guardian flag required)
- 18–65 adult
- ≥ 66 invalid for an adult fare
Boundary values are where the rules change: 1/2 (infant/child), 17/18 (child/adult), 65/66 (adult/invalid). Under two-value boundary value analysis on the adult partition alone you need 17, 18, 65 and 66; with three-value analysis add 19 and 64.
What is wrong with the existing four:
- 66 is missing - the upper invalid boundary is never tested, so an off-by-one in the
<= 65check passes unnoticed. - 30 is redundant under equivalence partitioning - it is in the same partition as 18.
- 1/2 and 17/18 boundaries of the child/infant rules are not covered, and the guardian-flag rule is untested entirely.
- No invalid-input cases (negative, decimal, text, blank).
Minimum fix: 17, 18, 65, 66 plus the 1/2 boundary and invalid-input partitions. Note that boundary values depend on how 'integer 18 to 65' is specified - if decimals are accepted, 17.99 and 65.01 matter too.
2. For the order state machine, how many test cases are needed to cover every transition, and what does that coverage still miss?
Read the worked answer
Transitions to cover: (1) DRAFT→SUBMITTED, (2) SUBMITTED→APPROVED, (3) APPROVED→SHIPPED, (4) SUBMITTED→REJECTED, (5) REJECTED→DRAFT, (6) APPROVED→CANCELLED.
The minimum is two test cases, because APPROVED and SUBMITTED each have mutually exclusive exits that no single path can take:
- TC1: DRAFT→SUBMITTED→APPROVED→SHIPPED (covers 1, 2, 3)
- TC2: DRAFT→SUBMITTED→REJECTED→DRAFT→SUBMITTED→APPROVED→CANCELLED (covers 1, 4, 5, 2, 6)
So the six existing tests are not obviously insufficient on transition count alone - the problem is that the coverage measure says nothing about what is actually risky:
- Invalid transitions. The real defects live in the guard logic: can a DRAFT order ship? Can a SHIPPED order be cancelled? Can an approver approve their own order?
- Sequences (n-switch). Transition coverage tests each arrow once; defects appear in loops - reject, resubmit, reject again - and in repeated submissions.
- Data conditions attached to transitions (refund amount, seat availability, fare class).
- Concurrency/timing: two approvals arriving together.
3. Explain how 100% statement coverage with 68% branch coverage is possible, and evaluate the team lead's conclusion.
Read the worked answer
Statement coverage requires each executable statement to run at least once. Branch coverage requires each decision outcome to be taken. A decision with no else branch, or with an empty one, contributes only the true-outcome statements to the executable code: a test that takes the true path gives 100% of the statements but leaves the false branch untaken. Compound conditions (if approved && notExpired && amount <= limit) make the gap wider: short-circuit evaluation means a passing test can skip whole sub-conditions. So 68% branch with 100% statement is the expected signature of a suite that exercises the happy path and never exercises the rejections.
The team lead's conclusion is unsound. Statement coverage is the weakest structural measure: it can be maximised by tests that walk the successful workflow, which is exactly what an order system's defects are not about. For a workflow, argue for branch/decision coverage on the guard logic plus explicit invalid-transition tests, and state a target for the release (e.g. 100% branch coverage on the approval/cancel guards, not an organisation-wide percentage). Coverage is a measure of what the tests exercised - not of whether they were good tests, and not a substitute for risk analysis.