Selecting test data

Selecting and Justifying Test Data

Knowing the three categories of test data is only the first step. The harder skill is looking at a specific algorithm and deciding exactly which values to test - then being able to explain why each value was chosen. This is what examiners mean by "select and justify": the selection is the list of test values, and the justification is the reasoning that explains what each value is designed to reveal.

A complete justification answers three questions for each test value:

  1. What category does it belong to? (normal, boundary, or erroneous)
  2. Why was this specific value chosen? (e.g. it is the exact lower boundary, or it is just above the upper limit)
  3. What would a wrong answer tell you? (i.e. what error would it expose if the output is incorrect)

The tabs below show three different algorithms. For each one, read the pseudocode, then study the test data table - focusing on the "Justification" column, which models the reasoning expected in an exam answer.

Three Algorithms - Three Test Plans

Year Group Checker (valid range: 7 to 13 inclusive)

INPUT year
IF year >= 7 AND year <= 13 THEN
    OUTPUT "Valid year group"
ELSE
    OUTPUT "Invalid year group"
ENDIF

How to derive the test data: the algorithm has two comparison conditions (>=7 and <=13). Each produces two boundary values: 6 and 7 for the lower limit; 13 and 14 for the upper. Normal data should be clearly inside the range. Erroneous data tests wrong type.

ValueCategoryExpected outputJustification
10NormalValid year groupMiddle of the valid range - confirms basic logic works for a typical input.
6BoundaryInvalid year groupJust below the lower limit. If the algorithm incorrectly uses > instead of >=, this value would not catch it - but it confirms the area just below is correctly rejected.
7BoundaryValid year groupExactly at the lower limit. If >= is incorrectly written as >, this value returns "Invalid" - directly exposing the comparison error.
13BoundaryValid year groupExactly at the upper limit. Tests whether 13 is correctly included.
14BoundaryInvalid year groupJust above the upper limit. Confirms the first value above the range is rejected.
"ten"ErroneousError / rejectedWrong data type. Tests whether the program handles a non-integer input without crashing.

PIN Validator (valid: exactly 4 digits, all numeric)

INPUT pin
IF LEN(pin) == 4 AND pin IS_NUMERIC THEN
    OUTPUT "Valid PIN"
ELSE
    OUTPUT "Invalid PIN"
ENDIF

How to derive the test data: there are two independent conditions - length (exactly 4) and type (all digits). Each condition needs to be tested when met and when not met. Boundary testing for length means 3, 4, and 5 characters. The type check needs both a fully numeric and a mixed-character test.

ValueCategoryExpected outputJustification
"5823"NormalValid PIN4 digits, all numeric - a typical correct PIN. Confirms the core logic accepts valid input.
"123"BoundaryInvalid PINOne character too short. Confirms length = 3 is correctly rejected.
"12345"BoundaryInvalid PINOne character too long. Confirms length = 5 is correctly rejected.
"58a3"ErroneousInvalid PINCorrect length but contains a letter. Tests the IS_NUMERIC condition independently of the length check.
""ErroneousInvalid PINEmpty string. Tests behaviour when no input is given - a common real-world edge case.

Score Grader (boundaries: A=90+, B=75+, C=60+, D=40+, F=below 40)

INPUT score
IF score >= 90 THEN
    OUTPUT "A"
ELSEIF score >= 75 THEN
    OUTPUT "B"
ELSEIF score >= 60 THEN
    OUTPUT "C"
ELSEIF score >= 40 THEN
    OUTPUT "D"
ELSE
    OUTPUT "F"
ENDIF

How to derive the test data: with multiple grade boundaries, each threshold (40, 60, 75, 90) needs testing both at and just below. The range 0 to 100 also needs testing at its extremes (0 and 100). Scores below 0 or above 100 are erroneous.

ValueCategoryExpected outputJustification
50NormalDClearly in the D range - tests the algorithm works for a straightforward case.
90BoundaryAExactly at the A threshold. Tests whether >= 90 correctly includes 90.
89BoundaryBJust below the A threshold. If the condition were > rather than >=, this would be fine - but 90 would give the wrong grade.
75BoundaryBExactly at the B threshold. Tests the boundary between B and C.
40BoundaryDExactly at the D/F boundary - the most critical threshold, as failing to include 40 would wrongly classify a passing score as F.
0BoundaryFMinimum possible score. Tests the algorithm at the bottom of the valid range.
100BoundaryAMaximum possible score. Tests the algorithm at the top of the valid range.
-1ErroneousError / rejectedBelow 0 - an impossible score. Tests robustness against invalid input.
101ErroneousError / rejectedAbove 100 - an impossible score. Tests robustness at the upper extreme.

 Key Takeaways

  • Selecting test data means identifying which specific values to test. Justifying test data means explaining why each value was chosen and what error it would expose if the output is wrong.
  • The starting point is always the algorithm's conditions: every comparison operator and every stated limit generates a set of boundary values that must be tested.
  • Each grade boundary, age limit, or length threshold needs at least two boundary tests: the value exactly at the limit (which should be accepted) and the value just outside it (which should be rejected or produce a different result).
  • When an algorithm has multiple independent conditions (e.g. length AND type), each condition should be tested in isolation as well as in combination - this ensures both checks are working independently.
  • Erroneous data must be justified too: "tests what happens when an impossible or wrong-type value is entered" is a complete justification for this category.