Skip to content

unittest Module Complexity

The unittest module provides a framework for unit testing with test cases, fixtures, and test runners.

Complexity Reference

Operation Time Space Notes
TestCase() O(1) O(1) Create test case
setUp()/tearDown() O(s) O(1) s = setup time
Assertion O(1) O(1) Check condition
Run test suite O(n*t) O(n) n = tests, t = per-test

Basic Test Case

import unittest

# Define test class - O(1)
class TestCalculator(unittest.TestCase):

    def setUp(self):  # O(s) - called before each test
        self.calc = Calculator()

    def tearDown(self):  # O(1) - called after each test
        pass

    def test_add(self):  # O(1)
        result = self.calc.add(2, 3)
        self.assertEqual(result, 5)  # Assert

    def test_subtract(self):  # O(1)
        result = self.calc.subtract(5, 3)
        self.assertEqual(result, 2)

# Run tests - O(n*t)
if __name__ == '__main__':
    unittest.main()  # O(n*t) - run all

Assertions

import unittest

class TestAssertions(unittest.TestCase):

    def test_equality(self):
        self.assertEqual(1, 1)           # O(1)
        self.assertNotEqual(1, 2)        # O(1)

    def test_truth(self):
        self.assertTrue(True)            # O(1)
        self.assertFalse(False)          # O(1)

    def test_membership(self):
        self.assertIn(1, [1, 2, 3])      # O(n) for list; O(1) avg for set/dict
        self.assertNotIn(4, [1, 2, 3])   # O(n) for list; O(1) avg for set/dict

    def test_types(self):
        self.assertIsInstance('text', str)  # O(1)
        self.assertIsNone(None)             # O(1)

    def test_exceptions(self):
        with self.assertRaises(ValueError):
            int('abc')  # O(1) - verify exception

Test Fixtures

import unittest

class TestWithFixtures(unittest.TestCase):

    @classmethod
    def setUpClass(cls):  # O(1) - once per class
        cls.shared_resource = create_resource()

    @classmethod
    def tearDownClass(cls):  # O(1) - once at end
        cls.shared_resource.cleanup()

    def setUp(self):  # O(s) - before each test
        self.data = []

    def test_append(self):
        self.data.append(1)
        self.assertEqual(len(self.data), 1)

Test Suite

import unittest

# Load tests - O(n)
loader = unittest.TestLoader()
suite = loader.loadTestsFromTestCase(TestCalculator)  # O(n)

# Run suite - O(n*t)
runner = unittest.TextTestRunner(verbosity=2)
result = runner.run(suite)  # O(n*t)

# Check results - O(1)
if result.wasSuccessful():
    print("All passed")

Mocking

import unittest
from unittest.mock import Mock, patch

class TestWithMocks(unittest.TestCase):

    def test_with_mock(self):
        # Create mock - O(1)
        mock_obj = Mock()
        mock_obj.method.return_value = 42

        # Use mock - O(1)
        result = mock_obj.method()
        self.assertEqual(result, 42)

    @patch('module.function')
    def test_with_patch(self, mock_func):  # O(1)
        mock_func.return_value = 'mocked'
        result = call_function()
        self.assertEqual(result, 'mocked')

Running Tests

# Run all tests in file
python -m unittest test_module.py  # O(n*t)

# Run specific test
python -m unittest test_module.TestClass.test_method  # O(1)

# Discover and run all tests
python -m unittest discover  # O(n*t)

# Verbose output
python -m unittest -v  # O(n*t)

Version Notes

  • Python 2.x: unittest available (as unittest2 backport)
  • Python 3.x: Built-in with enhancements
  • Python 3.4+: Subtests added

Best Practices

Do:

  • Write independent tests
  • Use setUp/tearDown
  • Name tests clearly
  • Test one thing per test
  • Use mocks for dependencies

Avoid:

  • Test interdependencies
  • Testing implementation details
  • Huge test methods
  • Ignoring test failures