Introduction to Unit Testing
Unit testing is a method of testing individual units of source code to determine if they are fit for use. Python's unittest
module provides tools for constructing and running tests.
# test_calculator.py
import unittest
def add(a, b):
return a + b
class TestCalculator(unittest.TestCase):
def test_add(self):
self.assertEqual(add(2, 3), 5)
self.assertEqual(add(-1, 1), 0)
self.assertEqual(add(0, 0), 0)
if __name__ == '__main__':
unittest.main()
# Run with: python -m unittest test_calculator.py
This simple test case demonstrates the basic structure of unit tests in Python. The unittest
module provides a rich set of assertions for verifying expected behavior.
Test Organization
Proper test organization is crucial for maintainable test suites. Python projects typically follow these conventions:
# Project structure
project/
├── mypackage/
│ ├── __init__.py
│ ├── module1.py
│ └── module2.py
└── tests/
├── __init__.py
├── test_module1.py
└── test_module2.py
# test_module1.py example
import unittest
from mypackage.module1 import some_function
class TestModule1(unittest.TestCase):
def setUp(self):
# Runs before each test method
self.test_data = [1, 2, 3]
def tearDown(self):
# Runs after each test method
del self.test_data
def test_some_function(self):
result = some_function(self.test_data)
self.assertIsInstance(result, list)
self.assertEqual(len(result), 3)
The setUp()
and tearDown()
methods allow you to define instructions that will be executed before and after each test method.
Common Assertions
The unittest
module provides many assertion methods to check for and report failures:
class TestAssertions(unittest.TestCase):
def test_assertions(self):
# Equality
self.assertEqual(3 + 2, 5)
self.assertNotEqual(3, 5)
# Boolean conditions
self.assertTrue(1 == 1)
self.assertFalse(1 == 2)
# Identity
self.assertIs(None, None)
self.assertIsNot(1, True)
# Membership
self.assertIn(3, [1, 2, 3])
self.assertNotIn(4, [1, 2, 3])
# Exceptions
with self.assertRaises(ValueError):
int('not a number')
# Approximate equality
self.assertAlmostEqual(0.1 + 0.2, 0.3, places=7)
self.assertNotAlmostEqual(0.1 + 0.2, 0.4, places=7)
These assertions help verify various conditions in your tests, making it easy to check that your code behaves as expected.
Advanced Testing Techniques
For more complex scenarios, Python offers several advanced testing techniques:
# Mocking and patching
from unittest.mock import Mock, patch
class TestAdvanced(unittest.TestCase):
def test_mock(self):
# Create a mock object
mock = Mock()
mock.method.return_value = 42
self.assertEqual(mock.method(), 42)
@patch('os.getcwd')
def test_patch(self, mock_getcwd):
mock_getcwd.return_value = '/fake/directory'
self.assertEqual(os.getcwd(), '/fake/directory')
def test_subtests(self):
# Parameterized testing with subtests
for a, b, expected in [(1, 1, 2),
(2, 3, 5),
(0, 0, 0)]:
with self.subTest(a=a, b=b, expected=expected):
self.assertEqual(add(a, b), expected)
@unittest.skip("demonstrating skipping")
def test_skip(self):
self.fail("shouldn't happen")
@unittest.skipIf(True, "conditionally skipped")
def test_skip_if(self):
self.fail("shouldn't happen")
These techniques allow you to test complex scenarios, isolate components, and manage test execution more effectively.
Alternative Testing Frameworks
While unittest
is powerful, Python offers other testing frameworks with different features:
# pytest example (install with: pip install pytest)
# test_with_pytest.py
def add(a, b):
return a + b
def test_add():
assert add(2, 3) == 5
# Run with: pytest test_with_pytest.py
# doctest example (tests in docstrings)
def multiply(a, b):
"""Multiply two numbers.
>>> multiply(2, 3)
6
>>> multiply('a', 3)
'aaa'
"""
return a * b
if __name__ == "__main__":
import doctest
doctest.testmod()
# Run with: python -m doctest -v example.py
pytest offers a more concise syntax and powerful features, while doctest allows you to embed tests in docstrings.
Python Unit Testing Videos
Master Python unit testing with these handpicked YouTube tutorials:
Learn the fundamentals of unittest:
Modern testing with pytest:
Isolating components for testing:
Effective testing approaches: