Debugging: Reproduce, Inspect and Verify
Find why a total is one mark too high
A report totals marks 40 and 35 as 76 instead of 75. The loop appears reasonable, so changing random operators would risk introducing another mistake.
Debugging is a process of reproducing a failure, comparing intended and actual behavior, and narrowing the cause with evidence. A fix should address the cause and be rechecked against the original failure.
Reproduce
Write exact input and expected output.
Inspect state
Find the first point where execution differs from the model.
Verify a fix
Check the failing case and relevant boundaries.
Find the extra one before guessing
Initialization
The total is already wrong before any addition.
1 instead of 0First addition
The extra one remains visible.
41 instead of 40Final result
Both marks were added to the wrong initial value.
76 instead of 75
A small input gives a trace you can explain
Write the expected values before inspecting the implementation: zero initially, forty after the first mark, seventy-five after the second. Compare each transition rather than only the final output.
Logs can expose state, while a debugger breakpoint can pause and inspect local values and the call stack. Use either to test one hypothesis at a time. Do not change unrelated code merely because it is nearby.
Before starting, review running totals across iterations. These examples use JavaScript; other languages can use different syntax and rules.
Observe the faulty intermediate values
The program deliberately starts total at one. The first addition gives 41 and the second gives 76. That locates the divergence at initialization, not at the addition operator.
This is valid JavaScript with an incorrect rule for the intended sum. There is no thrown exception to catch.
JavaScript · local teaching example
const marks = [40, 35];
let total = 1;
for (const mark of marks) {
total += mark;
console.log(total);
}Expected output
41
76Change the cause and re-run the trace
Starting at zero removes the unexplained extra mark. The outputs now agree with the predicted intermediate state.
A correct result for one example is evidence, not proof for every input. Add a case that would expose the same initialization problem without additions.
JavaScript · local teaching example
const marks = [40, 35];
let total = 0;
for (const mark of marks) {
total += mark;
console.log(total);
}Expected output
40
75Apply the rule to a small change
Check the corrected rule on an empty array. Explain why this is a useful regression case.
Worked answer
The total should remain zero. The old implementation would have returned one even without marks, so this boundary directly exposes the original cause.
JavaScript · local teaching example
const marks = [];
let total = 0;
for (const mark of marks) total += mark;
console.log(total);Expected output
0Recognize mistakes and limits
A symptom may be downstream of a wrong input or an earlier mutation. Inspect where the first incorrect state appears rather than patching the final display.
Logs can leak private school data and alter timing in sensitive concurrent cases. Use minimal relevant evidence, remove temporary noise and preserve an automated regression check for the confirmed bug.
For the language or tool rules used here, see JavaScript errors and handling.
Check the core idea
JavaScript · code for this question
const marks = [40, 35];
let total = 1;
for (const mark of marks) {
total += mark;
console.log(total);
}Apply the idea to a new situation
Turn a confirmed cause into a repeatable check
Reproduce the failure, predict intermediate values, inspect the earliest divergence and fix its cause. Re-run the original case and a relevant boundary, then keep a regression test.
Connect this idea with failure categories and automated expectations.
Reaching the recap and completing the quizzes are separate milestones.