Chapter 12: Debugging, Logging & Testing
Techniques to find and fix bugs, record events with logging, and write automated tests.
Downloadchapter12.py
Objectives
- Use print() and
pdbfor interactive debugging. - Configure the
loggingmodule: levels, formatters, handlers. - Differentiate
assertstatements from exceptions and logs. - Write basic unit tests with
unittestand run them. - Learn about third-party testing tools like
pytest.
1. Debugging Techniques
Start with strategic print() calls:
def compute(x, y):
print("DEBUG:", x, y)
return x / y
compute(5, 0) # inspect inputs
Use the built-in pdb for breakpoints:
import pdb
def buggy():
a = 1
pdb.set_trace() # pause here
b = 0
return a / b
buggy()
2. Logging Module
A better alternative to prints; supports levels and destinations:
import logging
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(message)s",
datefmt="%H:%M:%S"
)
logger = logging.getLogger(__name__)
logger.debug("Debugging info")
logger.info("Startup complete")
logger.warning("Low disk space")
logger.error("An error occurred")
Create file or stream handlers for flexible output:
fh = logging.FileHandler("app.log")
fh.setLevel(logging.WARNING)
logger.addHandler(fh)
3. Assertions
Use assert to check invariants during development:
def divide(a, b):
assert b != 0, "b must not be zero"
return a / b
Note: assert statements are removed when Python runs with -O.
4. Unit Testing with unittest
Create test cases by subclassing unittest.TestCase:
import unittest
from chapter12 import divide
class TestMath(unittest.TestCase):
def test_divide_normal(self):
self.assertEqual(divide(10, 2), 5)
def test_divide_zero(self):
with self.assertRaises(AssertionError):
divide(5, 0)
if __name__ == "__main__":
unittest.main()
Run tests with python -m unittest or integrate into your CI.
5. pytest Overview
pytest offers concise syntax and fixtures:
# test_chapter12.py
import pytest
from chapter12 import divide
def test_divide():
assert divide(9, 3) == 3
def test_divide_zero():
with pytest.raises(AssertionError):
divide(1, 0)
Install with pip install pytest and run pytest.
Exercises
- Insert
pdb.set_trace()into a small function and step through it. - Switch
print()calls tologgingat various levels and inspect the log file. - Add
assertchecks to a data-validation function. - Write
unittesttests for a simple calculator module (add, sub, mul, div). - Try rewriting those tests in
pyteststyle and compare.