Unit 07 · lesson
Build the Bug Case File
Core path: 30 minutes
A good debugging session leaves behind more than fixed code.
It leaves a trail showing what failed, what evidence mattered, what hypothesis you tested, and why the final repair is believable.
That trail is your bug case file.
Separate symptom from cause
Suppose the program crashes on:
average = total / reading_count
The visible failure might be division by zero.
The cause may be earlier: the program accepted reading_count = 0 even though calculating an average with zero readings makes no sense.
The line where a failure appears and the place where the bad state entered the system are not always the same.
That distinction is one of the biggest jumps from beginner debugging to useful debugging.
Write the timeline
For one bug from Lesson 4, reconstruct the sequence:
input or earlier state
↓
first incorrect value or decision
↓
code continues
↓
visible symptom / traceback / wrong output
↓
investigation
↓
controlled repair
↓
verification
Do not skip straight from symptom to fix.
The middle is where the reasoning lives.
Use a hypothesis that can be wrong
Weak:
Something is wrong with the loop.
Stronger:
readingis still a string becauseinput()was not converted, so the accumulator cannot perform the numeric update I expect.
The stronger statement can be tested:
print(type(reading))
print(type(total))
or with the debugger.
A useful hypothesis makes a prediction about what evidence you should see.
Capture before and after evidence
For one repaired bug, keep:
Before
input:
actual output/error:
relevant variable values:
After
same input:
new output:
relevant variable values:
The same test input matters. If you change the input and the code at the same time, you have made the comparison weaker.
One controlled change. Same test. Compare evidence.
Use the debugger to answer a question
Set a breakpoint only after you can finish this sentence:
I am stopping here because I need to know whether ________.
Examples:
I need to know whether
readingis still a string.
I need to know whether
totalchanges after each iteration.
I need to know which branch receives
average = 90.
A breakpoint without a question is just a pause button.
Build a regression check
Choose one bug you fixed.
Write down the exact input that exposed it.
After every later repair, run that same input again.
That is a manual regression test: proof that later changes did not silently reintroduce an earlier failure.
Week 14 will automate this idea with pytest. Right now, the habit matters more than the tool.
Your case file
Create debugging-case-file.md with three bugs from the console:
# Debugging Case File
## Case 1
Symptom:
Evidence:
First incorrect state I found:
Hypothesis:
One change:
Verification:
Regression check:
## Case 2
...
## Case 3
...
At least one case must be a logic bug that did not produce a traceback.
At least one case must include debugger evidence.
At least one case must show that the visible failure occurred later than the actual cause.
The rule worth carrying forward
When something fails, your first question should not be:
What code should I change?
Ask:
What do I know happened, and what evidence would narrow the cause?
That habit is slower for about five minutes.
Then it starts saving hours.
Movie hacking loves the keyboard. Real debugging loves the evidence.
Reader workbench
Create debugging evidence before changing code
This is the Unit's one-file practice surface. Read the code, predict one result, run it, then change a value, input, condition, or boundary and explain why the evidence changed. Multi-file projects, Git, terminals, packages, and live services still belong in the full development workspace.
Run the code to see output.
This runs in an isolated Python worker in your browser. Your edits stay in this browser until you reset them.