To design a boundary test, find every edge in the rule, list the values just below, on and just above each edge, write what the rule says should happen, and only then run the code. The table is the test. The code is what you check against it.
Boundary tests catch the commonest small errors in selection and loops. They also give you evidence that a fix worked, instead of a feeling.
Why do errors gather at the edges?
Most of a rule’s range is unambiguous. A mark of 30 fails and a mark of 90 is an A under almost any version of the code. The difference between “greater than” and “greater than or equal to” only shows at the exact value.
So a test with comfortable values can pass while the code is wrong. The bug sits in the one place you did not look.
How to design the test
- Write the rule in plain words, including the valid range.
- Mark each edge where the outcome changes.
- List values just below, on and just above each edge, plus one typical value.
- Fill the expected column from the rule, before running anything.
- Run the code and fill the actual column.
- Fix the code, then rerun the whole table, not only the failed row.
Worked example
Rule: marks run from 0 to 100.
A mark of 80 or more gets “A”. A mark of 50 to 79 gets “Pass”. Below 50 gets “Fail”.
The code a student wrote:
def grade(mark):
if mark > 80:
return "A"
elif mark > 50:
return "Pass"
else:
return "Fail"
The edges are 50 and 80. The table:
| Mark | Expected | Actual | Result |
|---|---|---|---|
| 0 | Fail | Fail | ok |
| 49 | Fail | Fail | ok |
| 50 | Pass | Fail | wrong |
| 79 | Pass | Pass | ok |
| 80 | A | Pass | wrong |
| 100 | A | A | ok |
Two rows fail, both exactly on an edge.
The cause is the same in both places: > should be >=. After changing both, rerun all six rows. All should now agree.
The mistake to watch for
A student sees that 50 gives the wrong result, changes that line and reruns only that row. It passes, so the student stops. The fault at 80 is still there.
A second version of the mistake is to test only 30, 65 and 90. All three pass with the broken code, so the student concludes the code is fine.
The correction: choose values from the edges, and rerun the complete table after every edit.
Check yourself
1. A rule says “child ticket if age is under 13”. Which values test the edge?
Show answer
12 (child) and 13 (not a child), and 14 as a value just above. The edge is at 13.
2. A rule says “pass if mark is at least 50”. Write the two most useful test values and their expected results.
Show answer
49 gives Fail and 50 gives Pass. Those two sit on either side of the edge.
3. With the broken grade code above, would testing 30, 65 and 90 reveal the bug?
Show answer
No. 30 gives Fail, 65 gives Pass and 90 gives A, all correct. Only 50 and 80 expose the fault.
Where this leads next
The lessons on designing normal, boundary and invalid test data and identifying an untested branch go further. To practise the first step, see creating a minimal reproducible learning example. You can run small original exercises in the safe Python reasoning sandbox.
When tests pass but you still cannot say why, one-to-one Computer Science tuition gives you a teacher to reason through the rule with. The Computer Science learning guide shows how testing fits into the subject.