Your first TestCase

unittest · Essentials · 9 min

Automated tests let you change code with confidence; unittest needs nothing beyond Python itself.

A test in unittest is a method on a subclass of unittest.TestCase whose name starts with test. Each method checks one behaviour using assertion methods such as self.assertEqual(actual, expected).

class TestSlugify(unittest.TestCase):
    def test_spaces_become_dashes(self):
        self.assertEqual(slugify("Hello World"), "hello-world")

The framework creates a fresh instance of the class for every test method, so tests don't share instance state. A test passes if the method returns normally, fails if an assertion fails (AssertionError), and is reported as an error if any other exception escapes.

Running: put unittest.main() under if __name__ == "__main__": and run the file, or use python -m unittest (next lessons). The runner prints a dot per passing test, F for failures and E for errors, then details and a summary.

Conventions:

  • test files named test_*.py, classes Test...,
  • one behaviour per test, with a name that describes it,
  • arrange, act, assert: set up inputs, call the code, check the result.

Use the assert* methods rather than bare assert: they give informative failure messages and still work under python -O.

Example

import unittest

def slugify(text: str) -> str:
    return "-".join(text.lower().split())

class TestSlugify(unittest.TestCase):
    def test_spaces_become_dashes(self):
        self.assertEqual(slugify("Hello World"), "hello-world")

    def test_collapses_whitespace(self):
        self.assertEqual(slugify("  a   b "), "a-b")

    def test_deliberately_wrong(self):
        self.assertEqual(slugify("X"), "X")    # fails: 'x' != 'X'

if __name__ == "__main__":
    unittest.main(exit=False)
# .F.   (methods run in alphabetical order)
# FAIL: test_deliberately_wrong (__main__.TestSlugify...)
# AssertionError: 'x' != 'X'
# Ran 3 tests in 0.000s
# FAILED (failures=1)

Remember

  • Subclass TestCase and name methods test_*
  • Each test method runs on a fresh instance
  • Failures come from assertions; other exceptions are errors

Watch out for

  • Naming a method check_something; only methods starting with 'test' are collected.

Check yourself

  1. A test method raises KeyError from the code under test. How does unittest report it?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.python.org/3/library/unittest.html#basic-example