Jed Rembold
September 15, 2025
If debugging is the process of removing software bugs, then programming must be the process of putting them in.
Edsger W. Dijkstra
Concentrate on what your program IS doing, instead of what it SHOULD be doing.
Let Python help you: print or log the state of different variables.
Stop and read. The documentation. The error messages.
The rich library offers some very
pretty error messages: install with
pip install rich
At the top of your code, then include:
from rich.traceback import install
install(show_locals=True)Use PythonTutor or a debugger to track EXACTLY what is happening in your program.
Don’t make random changes to your code in the hopes that it will miraculously start working.
Talk it out.
Test your code as you go! Either manually or automatically.
You can use Python’s assert statement
to write test functions, which take the form:
assert |||condition|||
where |||condition||| is any operation
that returns a True or
False
Assert statements “expect” a condition to yield a
True, and if they do, nothing happens
If an assert condition evaluates to
False, an error is raised
Naming your test functions starting with the word
test_ will make them automatically
discoverable by other tools
Suppose we wanted to write some checks of the
greatest_factor function from last class
def test_greatest_factor():
"""Runs several tests on greatest_factor"""
assert greatest_factor(10) == 5
assert greatest_factor(7) == 1
assert greatest_factor(51) == 17
assert greatest_factor(9) == 3
How could you represent the number of items shown to the right in a binary representation?
== for
floating numeric comparisons! Rounding might result in unexpected
falsehoods
0.1 + 0.1 + 0.1 != 0.3