Python unittest
This page shows how to write and run tests with the Python unittest module. It covers test classes, assertions, setup and teardown, discovery, mocking, and common mistakes.
unittest ships with Python
The unittest module is part of the Python standard library. You do not install any package to use it. Import unittest at the top of your test file and start writing tests.
A test is a class that inherits from unittest.TestCase. Each method that starts with test_ is one test. The test runner finds these methods and runs them.
Write assertions
Use the assert methods of TestCase to check results. assertEqual compares two values. assertTrue checks that a value is true. assertRaises checks that a call raises an expected exception.
The example below tests a small function. The first test passes because 2 plus 3 is 5. The second test passes because the function raises ValueError for a negative number.
import unittest
def add_positive(a, b):
if a < 0 or b < 0:
raise ValueError("negative input")
return a + b
class TestAddPositive(unittest.TestCase):
def test_sum(self):
self.assertEqual(add_positive(2, 3), 5)
self.assertTrue(add_positive(1, 1) > 0)
def test_negative(self):
with self.assertRaises(ValueError):
add_positive(-1, 2)
if __name__ == "__main__":
unittest.main()
Use setUp and tearDown
setUp runs before each test method. tearDown runs after each test method. Use them to create and clean up test data.
The test runner makes a new instance of the test class for each test. So state in setUp does not carry from one test to the next. This design keeps tests independent.
The example below creates a fresh list in setUp. Each test gets its own empty list. The tearDown method clears the list after the test.
import unittest
class TestList(unittest.TestCase):
def setUp(self):
self.items = []
def tearDown(self):
self.items.clear()
def test_add(self):
self.items.append(1)
self.assertEqual(len(self.items), 1)
def test_empty(self):
self.assertEqual(self.items, [])
Find and run tests
Use python3 -m unittest discover to find all test files in the current directory. The default pattern is test*.py. The runner imports each file and runs the tests.
To run one test, give its dotted name. The name has the module, the class, and the method. For example, python3 -m unittest test_math.TestAddPositive.test_sum runs only that method.
The dotted name must match the import path. If the test file is in a package, include the package name in the path.
Fake a network call with mock
unittest.mock.patch replaces a function during a test. Use it to fake a network call. The test then runs fast and does not need a server.
The example below patches urllib.request.urlopen. The fake returns a small object with a read method. The test checks the parsed result and the call count.
import unittest
from unittest.mock import patch
import json
import urllib.request
def fetch_name():
with urllib.request.urlopen("https://example.com/api") as response:
return json.loads(response.read())["name"]
class TestFetchName(unittest.TestCase):
@patch("urllib.request.urlopen")
def test_fetch_name(self, mock_urlopen):
mock_urlopen.return_value.read.return_value = b'{"name": "Ada"}'
self.assertEqual(fetch_name(), "Ada")
mock_urlopen.assert_called_once()
Avoid common mistakes
Shared state between tests causes failures that depend on run order. Fix it by creating data in setUp, not at class level. A new instance runs per test, so setUp data stays separate.
Do not put asserts inside setUp. A failed assert in setUp hides which test failed. Fix it by moving the check into the test method.
Tests that depend on order break when you run one test alone. Fix it by making each test set up its own data. Do not rely on a test that ran before.
Catching too broad an exception hides real errors. Fix it by catching the exact exception type. Use assertRaises with that type.
Common questions
What is the difference between setUp and setUpClass?
setUp runs before each test method and gets a new instance. setUpClass runs once for the whole class and must be a classmethod.
How do I run one test?
Use python3 -m unittest with the dotted name of the test, such as test_math.TestAddPositive.test_sum.
How do I mock a function in unittest?
Use the unittest.mock.patch decorator or context manager. Give the import path of the function as a string.