Skip to main content
SingaporeComputer ScienceSyllabus dot point

How do we test software systematically and find the cause of a defect efficiently?

Design test cases using normal, boundary and erroneous data, distinguish levels of testing, and apply systematic debugging techniques

A focused answer to the H2 Computing outcome on testing and debugging. Choosing normal, boundary and erroneous test data, unit and integration and system testing, black-box versus white-box, and systematic debugging.

Generated by Claude Opus 4.88 min answer

Reviewed by: AI editorial process; not yet individually human-reviewed

Have a quick question? Jump to the Q&A page

Jump to a section
  1. What this dot point is asking
  2. The answer
  3. Examples in context
  4. Try this

What this dot point is asking

SEAB wants you to design test cases using normal, boundary and erroneous data, distinguish the levels and styles of testing, and apply systematic debugging. The central idea is that testing is deliberate, not random: you choose inputs that are most likely to expose faults, and when a test fails you locate the cause methodically rather than by guesswork.

The answer

Choosing test data

Good test data deliberately probes where bugs hide. Three categories:

  • Normal (valid) data - typical values well inside the acceptable range, confirming the program works for ordinary input.
  • Boundary data - values at the edges of the valid range and just outside it (for a range 0 to 100: test 0, 100, and -1, 101). Boundaries catch the common off-by-one errors.
  • Erroneous (invalid) data - values the program should reject: out of range, wrong type, empty input. These check that the program fails safely.

A thorough test set includes all three.

Levels of testing

Testing happens at increasing scope:

  • Unit testing - one component (a function or class) in isolation.
  • Integration testing - components working together, catching interface faults.
  • System testing - the whole system against its requirements.
  • Acceptance testing - the client confirms it meets their needs.

Black-box versus white-box

  • Black-box testing derives test cases from the specification, ignoring internal code - testing what the program should do.
  • White-box testing uses knowledge of the code structure to exercise specific paths, branches and conditions - testing how it does it (aiming for good code coverage).

The two are complementary: black-box checks behaviour, white-box checks internal logic.

Systematic debugging

When a test fails, locate the fault methodically:

  1. Reproduce the failure reliably with a minimal input.
  2. Locate the region - use print statements or a debugger's breakpoints, and bisection: check the program state at a midpoint, then halve the suspect region repeatedly.
  3. Hypothesise the cause, then test the hypothesis by inspecting variables or stepping through.
  4. Fix and retest, including a regression test so the bug cannot silently return.

This beats random edits, which often introduce new faults.

Examples in context

Example 1. Testing a date validator. A function checking calendar dates is tested with normal dates, boundaries (the 28th, 29th, 30th, 31st around month ends, and leap-year February 29), and erroneous inputs (month 13, day 0, text). The boundary cases around month lengths are exactly where validation bugs cluster, so they earn their place in the test set.

Example 2. Bisecting a regression. When a previously working report suddenly produces wrong totals, a developer uses bisection on the version history (and on the data pipeline) to find the change that introduced the fault, checking the midpoint each time. Halving the search space turns a vast hunt into a handful of checks.

Try this

Q1. For a field accepting ages 18 to 65 inclusive, give one boundary value and one erroneous value to test. [2 marks]

  • Cue. Boundary: 18 or 65 (and just-beyond 17 or 66); erroneous: a negative age, 0, or a non-numeric input.

Q2. Distinguish between unit testing and integration testing. [2 marks]

  • Cue. Unit testing checks a single component in isolation; integration testing checks that components work correctly together, catching interface faults.

Q3. Describe one systematic technique for locating a bug. [1 mark]

  • Cue. Bisection - check the program state at a midpoint and repeatedly halve the suspect region until the faulty line is isolated.

Exam-style practice questions

Practice questions written in the style of SEAB exam questions on this dot point, with worked answer explainers. The year tag is the paper they imitate, not the source.

Original6 marksA function accepts an exam mark from 0 to 100 inclusive and classifies it. Design a set of test data covering normal, boundary and erroneous cases, giving the value, its category and the expected behaviour for each.
Show worked answer →

Choose data that exercises the valid range, its edges, and invalid inputs:

Value Category Expected behaviour
55 normal accepted and classified normally
0 boundary (lower) accepted (lowest valid mark)
100 boundary (upper) accepted (highest valid mark)
-1 erroneous (just below) rejected as invalid
101 erroneous (just above) rejected as invalid
"abc" erroneous (wrong type) rejected as invalid

Normal data lies well inside the valid range; boundary data sits exactly at the limits (0 and 100) and just outside (-1, 101); erroneous data is invalid (out of range or wrong type). Boundaries and just-beyond values catch the most common off-by-one bugs.

Markers reward at least one normal value, both boundaries (0 and 100), and erroneous values including out-of-range and wrong-type inputs, each with the expected result.

Original5 marks(a) Distinguish between unit testing and integration testing. (b) Distinguish between black-box and white-box testing. (c) Describe one systematic technique for locating the cause of a bug.
Show worked answer →

(a) Unit testing tests an individual component (such as a single function) in isolation. Integration testing tests that separately working components interact correctly when combined - it catches interface and interaction faults that unit tests miss.

(b) Black-box testing chooses test cases from the specification without knowing the internal code - testing what it should do. White-box testing uses knowledge of the code's structure to exercise specific paths, branches and conditions - testing how it does it.

(c) A systematic technique: divide and conquer / bisection - narrow the region containing the fault by checking the program state at a midpoint (using print statements or a debugger's breakpoints), then repeatedly halving the suspect region until the faulty line is isolated. Other valid answers: stepping through with a debugger, or forming and testing a hypothesis about the cause.

Markers reward the unit-versus-integration distinction, the black-box (spec) versus white-box (code structure) distinction, and a genuine systematic debugging method.

Related dot points