CodeNebula
Python📦Standard Libraryintermediate

`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

snippet.py
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

unittest_basics.py
# 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)
Run command
python3 unittest_basics.py