unittest — Unit Testing Framework

The unittest module provides a rich set of tools for constructing and running tests. It is inspired by JUnit.

import unittest

Basic Test Case

import unittest

def add(a, b):
    return a + b

class TestMathOperations(unittest.TestCase):
    
    # Run before EACH test method
    def setUp(self):
        self.a = 10
        self.b = 5
        
    # Run after EACH test method
    def tearDown(self):
        pass

    # Test methods MUST start with 'test_'
    def test_add(self):
        result = add(self.a, self.b)
        self.assertEqual(result, 15)
        
    def test_add_negative(self):
        self.assertEqual(add(-1, -1), -2)

if __name__ == '__main__':
    unittest.main()

Common Assertions

self.assertEqual(a, b)          # a == b
self.assertNotEqual(a, b)       # a != b
self.assertTrue(x)              # bool(x) is True
self.assertFalse(x)             # bool(x) is False
self.assertIs(a, b)             # a is b
self.assertIsNone(x)            # x is None
self.assertIn(a, b)             # a in b
self.assertIsInstance(a, b)     # isinstance(a, b)

Testing Exceptions

import unittest

def divide(a, b):
    if b == 0:
        raise ValueError("Cannot divide by zero")
    return a / b

class TestDivide(unittest.TestCase):
    def test_divide_by_zero(self):
        # Context manager style (preferred)
        with self.assertRaises(ValueError):
            divide(10, 0)
            
        # Or checking exception message
        with self.assertRaisesRegex(ValueError, "Cannot divide"):
            divide(10, 0)

Skipping Tests

import unittest
import sys

class TestFeatures(unittest.TestCase):
    @unittest.skip("Work in progress")
    def test_new_feature(self):
        pass

    @unittest.skipIf(sys.platform.startswith("win"), "Does not run on Windows")
    def test_linux_feature(self):
        pass
        
    @unittest.expectedFailure
    def test_broken_function(self):
        self.assertEqual(1, 0)

Mocking (unittest.mock)

from unittest.mock import MagicMock, patch
import unittest

# Module to test
import requests

def get_user_name(user_id):
    response = requests.get(f"https://api.example.com/users/{user_id}")
    return response.json()['name']

class TestAPI(unittest.TestCase):
    
    @patch('requests.get')
    def test_get_user_name(self, mock_get):
        # Configure the mock
        mock_response = MagicMock()
        mock_response.json.return_value = {'name': 'Alice'}
        mock_get.return_value = mock_response
        
        # Call the function
        name = get_user_name(1)
        
        # Assertions
        self.assertEqual(name, 'Alice')
        mock_get.assert_called_once_with("https://api.example.com/users/1")

Running Tests

From the command line:

# Run all tests in a module
python -m unittest test_module.py

# Run a specific test class
python -m unittest test_module.TestClass

# Run a specific test method
python -m unittest test_module.TestClass.test_method

# Discover and run all tests in current directory
python -m unittest discover

Official Documentation

unittest — Unit testing framework

API Reference

Core Classes and Methods

Class/Method Description
unittest.TestCase A class whose instances are single test cases.
TestCase.setUp() Method called to prepare the test fixture. Called immediately before calling the test method.
TestCase.tearDown() Method called immediately after the test method has been called and the result recorded.
TestCase.assertEqual(a, b) Check that a == b.
TestCase.assertTrue(x) Check that bool(x) is True.
TestCase.assertRaises(exc, callable, *args) Test that an exception is raised when callable is called with arguments.

Mocking

Object Description
unittest.mock.MagicMock MagicMock is a subclass of Mock with default implementations of most of the magic methods.
@unittest.mock.patch(target) A function decorator to mock a target object during a test.