Card 05/ 09
Template Method in the Wild: Python's unittest.TestCase
The runner calls setUp, your test, then tearDown, in that order, for every test.
Python's unittest.TestCase is a template method you have probably already used. You subclass it and write setUp, tearDown and methods whose names begin with test, and you never write the code that calls them. That code is TestCase.run, the template method, and this card prints each call to show the order it enforces.
import inspect
import io
import sys
import unittest
class BasketTest(unittest.TestCase):
def setUp(self) -> None:
print("setUp")
self.basket: list[int] = []
def test_empty(self) -> None:
print(" test_empty")
self.assertEqual(sum(self.basket), 0)
def test_add(self) -> None:
print(" test_add")
self.basket.append(500)
self.assertEqual(sum(self.basket), 500)
def tearDown(self) -> None:
print("tearDown")
suite = unittest.defaultTestLoader.loadTestsFromTestCase(BasketTest)
unittest.TextTestRunner(stream=io.StringIO()).run(suite)
source = inspect.getsource(unittest.TestCase.run)
print("Python", sys.version.split()[0])
print("run calls setUp, the test and tearDown:", all(
name in source for name in ("_callSetUp", "_callTestMethod", "_callTearDown")))setUp
test_add
tearDown
setUp
test_empty
tearDown
Python 3.12.13
run calls setUp, the test and tearDown: TrueEach test runs between a fresh setUp and a tearDown, so test_add's item does not reach test_empty. The tests run in alphabetical order of their names, which is the default of the test loader, not the order they appear in the class. The last line checks the source of TestCase.run in Python 3.12.13, and confirms that it calls the internal methods that run setUp, the test and tearDown.
The parts map onto the template. TestCase is the abstract class and run is the template method. setUp and tearDown are hooks, with defaults that do nothing, and each test_ method is the step a subclass supplies. BasketTest is the concrete class.
This is the Hollywood principle at work: the framework calls you. Many frameworks are built this way, which is why learning to find the template method is often the quickest way to learn when your code will run.
← → move through sections and cards