Course outline · 0% complete

0/29 lessons0%

Course overview →

A Tiny Test Runner

lesson 1-3 · ~11 min · 3/29

One failure should not hide the rest

Plain asserts have a flaw: the program stops at the first failure, so you never learn whether the other tests pass. Real test tools like pytest and unittest solve this by running each test separately and printing a report.

We can build the heart of such a test runner in ten lines. The idea:

  1. write each test as a small function whose name starts with test_
  2. loop over the test functions
  3. call each one inside try/except AssertionError (exception handling from Advanced Python)
  4. print PASS or FAIL with the test's name, then a summary

Building it once demystifies every test framework you will ever meet. They all do this, plus conveniences.

Code exercise · python

Run the mini runner. Note test.__name__, a function attribute that holds the function's own name, which gives us readable output for free.

Quiz

Why does the runner call each test inside try/except AssertionError?

Code exercise · python

Your turn: the multiply function below has a bug, and the tests catch it. Run first to see the FAIL lines, then fix multiply so the report shows 3/3 passed.

Code exercise · python

One upgrade before moving on. Buggy code does not always fail an assert politely — it can crash with any exception, like the ZeroDivisionError here. Run this: the runner only catches AssertionError, so the whole run dies and the summary never prints. Add a second except clause, except Exception as e, that prints FAIL <name> (crashed: <type name>) using type(e).__name__, so the runner survives any crash. Real runners like pytest do exactly this.

Problem

In the runner above, one test fails with AssertionError but the loop keeps going and prints a summary at the end. What is the exact name of the exception type that a failing assert raises?