Testing & Debugging
- Distinguish syntax errors, runtime errors, and logic errors
- Design test cases that include typical, boundary, and invalid inputs
- Use tracing and test results to locate and fix a bug
Three kinds of errors
Programs fail in three distinct ways. A syntax error breaks the language’s grammar (a missing bracket or keyword) so the program will not run at all. A runtime error appears while the program is running and forces it to stop — dividing by zero, or accessing a list element that does not exist. The trickiest is a logic error: the program runs to completion and produces an answer, but the wrong answer, because the instructions do not correctly express what you intended. Logic errors are hardest to find precisely because nothing crashes.
Testing means trying to break it
To test a program is to run it on chosen inputs and check whether the output is what you expect. Good testing is deliberately adversarial: you pick inputs likely to expose flaws. Cover three categories — typical cases (ordinary expected input), boundary cases (the edges: the smallest and largest allowed values, an empty list, zero), and invalid cases (input the program should reject, like text where a number is expected). A program that works on typical input but crashes on an empty list has an untested boundary.
Finding the bug by tracing
Once a test fails, you debug: locate the cause and fix it. The most reliable technique is tracing — following the program step by step, tracking the value of each variable exactly as the computer would, until the value first becomes wrong. Adding temporary DISPLAY statements to print variable values at key points is a simple, powerful way to see where reality diverges from your expectation. The moment a variable holds an unexpected value, you have narrowed the bug to the lines just before it.
Trace this AP-pseudocode program and find the logic error. The programmer intended to display the larger of two numbers.
a ← 3
b ← 8
IF (a > b)
{
DISPLAY(a)
}
ELSE
{
DISPLAY(a)
}
- 1.Track the variables:
ais 3 andbis 8. - 2.Evaluate the condition
a > b: is 3 > 8? No, it is false, so the ELSE branch runs. - 3.The ELSE branch executes
DISPLAY(a), printing 3 — but 3 is the smaller number, so the output is wrong. - 4.Look at both branches: they both display
a. The ELSE branch should displayb. The fix is to change the ELSE branch toDISPLAY(b).
a; the ELSE branch should be DISPLAY(b). Tracing exposes the bug because the output disagrees with the intended "larger number."A program compiles and runs to completion without crashing, but it computes a student’s average as the sum of the scores instead of the sum divided by the count. What kind of error is this?
The exam loves the distinction: syntax = won’t run, runtime = crashes mid-execution, logic = runs but wrong. If a program produces an incorrect result without crashing, it is always a logic error.
A function computes the average of a list of numbers. Which single test input is most important for exposing a hidden bug that typical inputs would not reveal?
Build a habit of testing three buckets: typical, boundary (empty, zero, minimum, maximum), and invalid input. Most surprising bugs hide at the boundaries, not in the ordinary middle.
Answer the 2 checkpoints as you read.
Sign in to save your progress