Programming Fundamentals Using C++

L12 · Desk-Checking, Trace Tables, and Test-Case Design

Module 6 — Problem-Solving and Algorithm Design · Week 6 · Lecture 12 of 32 · 120 minutes Outcomes: CLO-4 · PF-6.3, PF-6.4 · LEARNING_OUTCOMES.md · Lab 3 week

Learning objectives

  1. Desk-check any straight-line, selection, or loop construct into a complete variable-state trace table, showing every variable's value before/after each step or iteration (PF-6.3).
  2. Design a test plan with named classes — normal, boundary, invalid — and justify why each case can reveal a distinct failure (PF-6.4).
  3. Report test evidence as expected-vs-actual with a one-line verdict, the format required in every lab and assignment for the rest of the semester (PF-6.4).

Prerequisites

L11 (IPO/design artifacts); L09–L10 (trace basics, loop patterns).

Concept sequence

  1. Why tracing beats re-reading (attention lies; tables don't)
  2. Trace-table mechanics: rows = steps/iterations, columns = variables
  3. Tracing selection and nested structures
  4. Test-case classes: normal, boundary, invalid (+ stress)
  5. Boundary analysis: where do bugs actually live
  6. Evidence reporting format (course standard)

Teaching topics (detailed)

C++ examples required

FileRole
buggy_off_by_one.cpp ✅3 seeded bugs (off-by-one, wrong boundary, inverted condition); students must find them by trace table first, then by test plan
(live) test_evidence.md template filled for the buggy programexpected-vs-actual table modeled live

Common student misconceptions

Conceptual explanation (beginner-first)

Last lecture planned programs on paper. Today: the two paper skills that catch bugs before and after running — the trace table and the test plan.

A trace table is you, playing computer. One column per variable (plus an output column), one row per step or loop pass. You fill rows without running anything, and — the crucial habit — you mark the row where the output first goes wrong, because the bug almost always lives above that row: the wrong value was computed earlier and merely showed up here. Tracing beats re-reading because attention lies (you skim past the wrong bound; the table doesn't) — this is why exams use trace questions: they measure whether you actually simulate code.

A test plan is the record of what you'll try after running: not random values, but named classes — normal (typical valid input), boundary (the edges: min, max, min−1, max+1, empty, zero), invalid (wrong type, out of range). The rule this course enforces: every boundary in your IPO chart must appear in your test plan. And the reporting format — input, expected, actual, verdict — becomes the evidence table in every lab and assignment from here to the final.

Terminology and definitions

TermDefinition
Desk checking / trace tablePaper execution: rows = steps/passes, columns = variables
Manifestation rowWhere the wrong output first appears — the bug is usually above it
Path markingAnnotating the trace with the branch taken at each decision
Test caseOne input + its expected output, chosen in advance
Normal classTypical valid inputs (2–3 cases)
Boundary classEdges of validity: min, max, min−1, max+1, empty, zero
Invalid classWrong type, out of range, sentinel-as-data
Expected vs actualThe evidence table: input, expected, actual, pass/fail
RegressionA previously passing case broken by a change
Limits of testingPassing tests ≠ correct; they prove behavior on those inputs only

Syntax and C++ examples

The worked trace (digit-sum loop, from L09):

passworkdigitdigitSumnote
enter907—0invariant holds
19077work % 10, then work /= 10
2907zero digit — pass still runs
30916loop condition now false → exit

And a test plan for an "age 3–120" validator:

inputclassexpected
25normalaccepted
3 / 120boundaryaccepted
2 / 121boundaryrejected
-1 / 1000boundaryrejected
"abc" / emptyinvalidrejected
// the seeded-bug program students trace and test:
for (int i{1}; i <= n; ++i)   // bug: should be i < n (off-by-one)
{
    sum += a[i];
}

Line-by-line code explanation

examples/buggy_off_by_one.cpp (three seeded bugs, found on paper first):

  1. Off-by-one: i <= n — the trace table shows the extra pass reading a[n] (one past the end): garbage in, garbage summed.
  2. Wrong boundary: a parking-fee tier whose else if (hours > 3) should be >= 3 — the boundary test case (exactly 3) exposes it; no normal case ever would.
  3. Inverted condition: if (!(score >= 60)) intended as "pass" — the path marking in the trace shows both branches firing in the wrong columns.
  4. The lesson ordering: trace → diagnosis sentence → then run; the expected-vs-actual table documents what the fix changes.

Output prediction questions (with answers)

  1. Trace s += i * 2 for i = 2..4 (s starts 0) — ? — rows (2, 4), (3, 10), (4, 18); final s = 18.
  2. Age validator: which class catches 120 vs 121? — Boundary class — normal cases never touch the edge.
  3. Expected 8.5, actual 8 — what do you ask first? — "Is this integer division truncation?" (L05's lesson re-appearing as a debugging question).
  4. Why mark the manifestation row? — The bug's cause computed an earlier wrong value; the symptom only shows it.
  5. A program passes all six planned tests. Is it correct? — Unknown: tests prove behavior on those inputs only.

Common errors and debugging examples

ErrorSymptomFix
Tracing from the symptom rowWrong fix downstream of the causeStart at row 1; mark the manifestation
One column for several variablesThe table hides its own bugOne column per variable, always
Skipping the output columnWrong answers go unnoticed mid-tableAdd the output column and use it
Tests only normal casesBoundaries silently brokenEvery IPO boundary in the plan
"Fix first, diagnose later"Shotgun editing (banned in L16)Diagnosis sentence before any edit
Evidence without expected values"It looked right" isn't evidenceExpected column filled before running

Classroom demonstrations

  1. The manifestation-row hunt: hand out a traced-wrong table; the class marks where output goes wrong, then walks upward to the causing line — the habit made physical.
  2. Boundary theatre: a fee program passes every normal case; input 3 (the boundary) breaks it — normal cases are the least informative, demonstrated live.
  3. Evidence formatting: fill the expected-vs-actual table on the board for the buggy program, before/after the one-line fix.

Guided student activities

Lab 3 (2 h, this lecture slot): labs/lab_manuals/lab_03 — trace-table drills on loops and branches, then bug-hunt in buggy_off_by_one.cpp with mandatory test-evidence tables. Lecture hour 2 = lab launch + demonstration of the evidence format on the board.

Practice problems

Summary

Trace tables simulate code row by row; the manifestation row points upward to the cause. Test plans cover normal, boundary, and invalid classes — with every IPO boundary present — and report evidence as expected-vs-actual with a verdict. Both skills are exam formats and daily habits; L16 turns them into a debugging method. Next (L13): functions — the shape programs take when they grow.

Exit ticket / formative assessment

  1. Trace two iterations: int s{0}; for (int i{2}; i <= 4; ++i) s += i * 2;
  2. Name the boundary cases for "valid age 3–120".
  3. A test shows expected 8.5, actual 8. What single question do you ask first?

Estimated time allocation (120 min)

SegmentMinutes
Recall (IPO quiz) + why tracing10
Trace-table mechanics with 2 worked examples35
Break10
Test-case classes + evidence format25
Lab 3 launch (trace + bug-hunt drills)30
Exit ticket + Module 7 preview10
Programming Fundamentals Using C++ · C++17 · 16 weeksBack to top ↑