PythonMastery
Python programs · Useful programs · intermediate

Mini unit test runner in Python

A small test runner that calls a function with test inputs, compares each result with the expected value, and prints PASS or FAIL with a summary.

A unit test calls one function with a known input and checks that the result is what you expect. This program is a tiny test runner. It runs a list of test cases, reports each one, and finds a real bug.

The program

python
def run_tests(func, cases):
    passed = 0
    for args, expected in cases:
        call = f"{func.__name__}({', '.join(repr(a) for a in args)})"
        try:
            result = func(*args)
        except Exception as error:
            result = f"{type(error).__name__}: {error}"
        if result == expected:
            passed += 1
            print(f"PASS  {call} == {expected!r}")
        else:
            print(f"FAIL  {call}: expected {expected!r}, got {result!r}")
    failed = len(cases) - passed
    print(f"\n{passed} passed, {failed} failed")
    return failed == 0


def is_leap_year(year):
    # bug on purpose: this forgets the rule for years divisible by 400
    return year % 4 == 0 and year % 100 != 0


cases = [
    ((2024,), True),
    ((2023,), False),
    ((1900,), False),
    ((2000,), True),
]
run_tests(is_leap_year, cases)
output
PASS  is_leap_year(2024) == True
PASS  is_leap_year(2023) == False
PASS  is_leap_year(1900) == False
FAIL  is_leap_year(2000): expected True, got False

3 passed, 1 failed

How it works

Try changing it

Fix the function with the full rule and run the tests again:

python
def is_leap_year(year):
    return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0

All 4 tests now pass. For real projects, use Python's built-in unittest module or the popular pytest package. They find test functions for you, show clear reports, and work the same way: call the code and compare the result with what you expected.

Learn the idea: Functions & Scoping, Testing with pytest, Errors & Exceptions: When Things Go Wrong