2.3.2

Testing

Iterative and final testing, types of test data and finding syntax and logic errors.

Learning Objectives

  • 1Understand the purpose of testing and the difference between iterative and final testing
  • 2Identify syntax and logic errors
  • 3Select normal, boundary, invalid and erroneous test data for a given scenario
  • 4Create or complete a test plan

The purpose of testing

Testing means deliberately trying to find problems in a program, not just checking that it seems to work. A program can look like it works while still having bugs hiding in cases you haven't tried yet.
The purpose of testing is to find and fix errors, and to check a program behaves as intended for a wide range of inputs, not just the ones the programmer expects. Testing should be thought of as an attempt to break the program, deliberately trying inputs likely to expose a problem, rather than only confirming it works in the easy, expected cases.
Testing should be approached destructively, actively trying to find faults, rather than simply demonstrating the program works for a few convenient examples. A program that passes a handful of easy tests may still contain serious bugs that only appear with boundary values, invalid input, or unusual combinations of data.

Iterative and final testing

Testing happens at two different points. Iterative testing happens throughout development, testing small parts (like individual sub-programs) as they're built. Final testing happens once the whole program is finished, checking it all works together.
Iterative testing takes place throughout development: individual modules or sub-programs are tested as they are written, and the results used to fix problems immediately, before moving on. Final (terminal) testing takes place once development is complete, testing the whole, finished program together, to check it meets its requirements as a complete system.
The key distinction examiners look for is WHEN each type of testing happens and WHAT is being tested, iterative testing checks individual modules during development, catching problems early and cheaply; final testing checks the complete, integrated program at the end, catching problems that only appear when all the parts work together.

Identifying syntax and logic errors

There are two error types to be able to spot: a syntax error breaks the rules of the programming language, so the code won't even run. A logic error lets the code run, but it produces the wrong result. This is covered in more depth in 2.1.2 Designing, creating and refining algorithms.
A syntax error breaks the grammatical rules of the programming language and stops it running or translating at all, e.g. a missing bracket or misspelt keyword. Examiners credit a range of examples: a misspelt keyword (printt), a missing or extra symbol (bracket, semicolon), mismatched quotes, an invalid variable name (starting with a number or containing a space), a reserved keyword used as a variable (print = 3), wrong capitalisation of a keyword (Print for print), or wrong indentation of a code block. A logic error does not stop the program running, but produces unexpected or incorrect output, e.g. dividing by the wrong variable. Testing is how both types of error get found, syntax errors are usually caught quickly by the IDE, logic errors require careful testing with varied data to expose.
Logic errors are harder to detect precisely because the program runs without crashing, the only way to catch them is to test with data where you already know what the correct output should be, then compare. This is why selecting good test data (see below) matters so much, weak test data can let a logic error go completely unnoticed.

Types of test data

There are four types of test data you need to know: normal (typical, sensible data), boundary (right on the edge of what's allowed), invalid (the right data type but out of range), and erroneous (completely the wrong data type). Normal and boundary data should be accepted; invalid and erroneous data should be rejected.
For a range of, say, 1 to 10: normal data is a typical, sensible value like 5, which should be accepted without error. Boundary data sits exactly on the edge of the valid range, like 1 or 10, and should still be accepted. Invalid data is the correct data type but outside the acceptable range, like 0 or 11, and should be rejected. Erroneous data is the wrong data type entirely, like the text "abc" where a number is expected, and should also be rejected.
The specification defines invalid and erroneous data as two separate categories, but real exam questions consistently group them together as "data a system would reject", since both are handled the same way in practice (rejected by the program). You should still know the precise technical difference (invalid = correct type, wrong range; erroneous = wrong type entirely) in case a question tests the distinction directly.
Test data for a valid range of 1 to 101105Accepted0 and below11 and aboveNormale.g. 5Typical data from themiddle of the rangeBoundarye.g. 1 and 10Sits exactly on theedge of the rangeInvalide.g. 0 or 11Right data type, butoutside the rangeErroneouse.g. "abc"The wrong data typeentirely

Selecting test data and creating a test plan

Choosing good test data for a scenario means picking at least one example of each type (normal, boundary, invalid, erroneous) that's relevant to that specific input. A test plan lists the test data used, what's expected to happen, and what actually happened.
When selecting test data for a given input, identify realistic values for each required category based on the actual constraints described in the scenario (e.g. "age must be 0 to 120" gives clear normal/boundary/invalid values). A test plan typically records, for each test: the test data used, its type (normal/boundary/invalid/erroneous), the expected result, and the actual result once run.
Test data must be justified using the specific scenario given, not a generic example unconnected to the actual input constraints, e.g. "boundary data of 120 ensures the upper age limit is handled correctly" is a much stronger answer than just stating a number with no reasoning. A complete test plan should include enough test cases to cover every required category of data for every input being validated.
Python· A function to validate age is between 0 and 120, ready to test
def validate_age(age):
    if age < 0 or age > 120:
        return "Invalid"
    return "Accepted"
OCR ERL· A function to validate age is between 0 and 120, ready to test
function validateAge(age)
    if age < 0 OR age > 120 then
        return "Invalid"
    endif
    return "Accepted"
endfunction

Exam Phrasing: Use These Exact Phrases

  • ✓Testing aims to find errors, not just to show a program works
  • ✓Iterative testing happens throughout development, testing individual modules; final testing happens once the whole program is complete
  • ✓A syntax error breaks the rules of the language and stops the program running; a logic error produces unexpected output
  • ✓Normal and boundary data should be accepted; invalid and erroneous data should be rejected
  • 💡When a question asks for test data, give a specific value for the type asked (e.g. an actual boundary number), not just the word "boundary".
  • 💡Never describe an error as the program "not working" or "stopping working", examiners mark that as too vague. Say what actually happens: it will not run or translate at all (syntax), or it runs but gives the wrong result (logic).
  • 💡A problem with a data type is not accepted as an example of a syntax error, and "incorrect grammar" on its own is not enough. Give a concrete example instead.
  • 💡Invalid and erroneous data are defined separately in the spec (invalid = correct type, wrong range; erroneous = wrong type entirely), but exam questions usually just group both as data that should be rejected.
  • 💡Justify your test data using the scenario given, e.g. explain why a specific boundary value matters for that particular input.
  • 💡Don't confuse iterative testing (during development, testing modules) with final testing (testing the whole finished program).

Wrong:

Boundary data is just another example of normal data

Right:

Boundary data sits exactly on the edge of the valid range, and is a distinct, specifically named category

Why it matters: Boundary values are the values most likely to reveal an off-by-one logic error (e.g. using > instead of >=).

Wrong:

Testing is about proving the program works

Right:

Testing should be approached destructively, actively trying to find errors

Why it matters: A program can pass a few easy tests and still contain bugs that only appear with less obvious data.

Wrong:

Invalid and erroneous data mean exactly the same thing

Right:

Invalid data is the correct type but out of range; erroneous data is the wrong type entirely

Why it matters: This is a real distinction in the specification, even though exam questions often group them together as "rejected" data.

Question:

A program accepts a percentage score from 0 to 100. State one example each of normal, boundary, invalid and erroneous test data for this input. [4]

💡 Attempt this before revealing the answer, practice makes perfect!

Model Answer:

Normal data: 75, a typical, sensible score within range. Boundary data: 0 or 100, right on the edge of the valid range. Invalid data: -5 or 101, the correct data type (a number) but outside the valid range. Erroneous data: "high", the wrong data type entirely (text instead of a number).

Mark Scheme:

  • 1Correct normal data example, a sensible value between 0 and 100
  • 2Correct boundary data example, exactly 0 or exactly 100
  • 3Correct invalid data example, a number outside 0 to 100
  • 4Correct erroneous data example, non-numeric data

Tap a card to flip it. Use the arrow keys to move and space to flip.

Known 0 Still learning 0
1 / 12

Exam-style questions. Have a go, then reveal the mark scheme to check your answer.

1.Explain the difference between iterative testing and final testing.

[2]

2.A program runs without crashing, but always calculates the wrong average. State whether this is a syntax error or a logic error, and explain your answer.

[2]

3.Explain why boundary data is important to include when testing a program.

[2]

4.Complete a test plan entry for testing the function below with the input -5. State the test data type, the expected result, and explain your reasoning.

[3]
Python· Function under test
def validate_age(age):
    if age < 0 or age > 120:
        return "Invalid"
    return "Accepted"
OCR ERL· Function under test
function validateAge(age)
    if age < 0 OR age > 120 then
        return "Invalid"
    endif
    return "Accepted"
endfunction

5.A program should accept whole numbers from 1 to 20. Give one example each of normal, boundary, invalid, and erroneous test data for this input.

[4]

6.A program accepts a whole number between 1 and 100. Describe a test plan for this program, explaining the purpose of each type of test data you would use.

[6]

The examiners' reports are the most useful and least read of the three: they say what candidates actually got wrong each year. All files are hosted by OCR.

Past-paper questions grouped by topic

The same OCR questions, sorted by topic rather than by year (via Physics & Maths Tutor).

2025
Paper 2

A question testing understanding of test data types (normal, boundary, invalid/erroneous) was answered very well by the vast majority of candidates, showing this topic is generally well taught. Examiners specifically noted that although the specification defines invalid data and erroneous data as separate categories, exam questions consistently group them together as data that a system would reject.

2024
Paper 2

Candidates who did less well on the paper commonly confused the concept of maintainability (2.3.1) with testing (2.3.2), these are two distinct required topics and should not be conflated: testing checks a program works correctly, maintainability is about how easy the code is to read and modify.