← Back to course

Testing & Debugging

You’ll be able to

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.

Worked example

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. 1.Track the variables: a is 3 and b is 8.
  2. 2.Evaluate the condition a > b: is 3 > 8? No, it is false, so the ELSE branch runs.
  3. 3.The ELSE branch executes DISPLAY(a), printing 3 — but 3 is the smaller number, so the output is wrong.
  4. 4.Look at both branches: they both display a. The ELSE branch should display b. The fix is to change the ELSE branch to DISPLAY(b).
Answer: This is a logic error: the program runs but prints 3, the smaller value. Both branches mistakenly display a; the ELSE branch should be DISPLAY(b). Tracing exposes the bug because the output disagrees with the intended "larger number."
Checkpoint

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?

On the exam

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.

Checkpoint

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?

Tip

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