`unittest` — Testing Framework
Python · Standard Library · Run with python3
Explanation
`unittest` is Python's built-in xUnit-style testing framework. Test cases extend `unittest.TestCase` and name methods `test_*`. `setUp`/`tearDown` run before/after each test; `setUpClass`/`tearDownClass` run once per class. Key assertions: `assertEqual`, `assertRaises`, `assertAlmostEqual`, `assertIn`, `assertIsInstance`, `assertRegex`. Run with `python -m unittest discover`. Modern projects often use `pytest` (which still runs `unittest.TestCase` tests) for its simpler fixtures and richer output.
Real-World Scenario
A `Calculator` class ships with a `TestCalculator` in the same repository. CI runs `python -m unittest discover tests/` on every PR. The `assertRaises` context manager verifies that invalid input raises the expected exception type. ```python import unittest from functools import lru_cache @lru_cache def factorial(n: int) -> int: if n < 0: raise ValueError(f"Factorial undefined for {n}") return 1 if n == 0 else n * factorial(n - 1) class TestFactorial(unittest.TestCase): def test_base_cases(self): self.assertEqual(factorial(0), 1) self.assertEqual(factorial(1), 1) def test_positive(self): self.assertEqual(factorial(5), 120) self.assertEqual(factorial(10), 3628800) def test_negative_raises(self): with self.assertRaises(ValueError): factorial(-1) def test_type_error(self): with self.assertRaises(TypeError): factorial(1.5) if __name__ == "__main__": unittest.main() ```
Quick Snippet
import unittest
from functools import lru_cache
@lru_cache
def factorial(n: int) -> int:
if n < 0:
raise ValueError(f"Factorial undefined for {n}")
return 1 if n == 0 else n * factorial(n - 1)
class TestFactorial(unittest.TestCase):
def test_base_cases(self):
self.assertEqual(factorial(0), 1)
self.assertEqual(factorial(1), 1)
def test_positive(self):
self.assertEqual(factorial(5), 120)
self.assertEqual(factorial(10), 3628800)
def test_negative_raises(self):
with self.assertRaises(ValueError):
factorial(-1)
def test_type_error(self):
with self.assertRaises(TypeError):
factorial(1.5)
if __name__ == "__main__":
unittest.main()Full Example
# Compile: python3 unittest_basics.py
# Output:
# ....
# OK
import unittest
from functools import lru_cache
@lru_cache
def factorial(n: int) -> int:
if n < 0:
raise ValueError(f"Factorial undefined for {n}")
if not isinstance(n, int):
raise TypeError(f"Expected int, got {type(n).__name__}")
return 1 if n == 0 else n * factorial(n - 1)
class TestFactorial(unittest.TestCase):
def test_base_cases(self):
self.assertEqual(factorial(0), 1)
self.assertEqual(factorial(1), 1)
def test_positive(self):
self.assertEqual(factorial(5), 120)
self.assertEqual(factorial(10), 3628800)
def test_negative_raises(self):
with self.assertRaises(ValueError):
factorial(-1)
def test_large(self):
self.assertGreater(factorial(20), factorial(19))
if __name__ == "__main__":
unittest.main(verbosity=1)
python3 unittest_basics.py