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, classesTest..., - 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.