How to Write Unit Tests in Python: A Practical Guide
Unit testing is a core practice in Python development that validates the smallest testable parts of your code in isolation. By writing unit tests, you catch bugs early, make refactoring safer, and keep your codebase reliable over time. In this guide, you’ll learn the essentials of writing effective unit tests using Python’s built-in unittest module and the lightweight pytest framework.
Before diving in, ensure you have a Python project set up. For this tutorial, we’ll use pytest because it requires less boilerplate and offers readable output. Install it with pip install pytest. Your test files should live in a tests/ directory or be named with a test_ prefix, so the test runner discovers them automatically.
Write Your First Test Function
Create a file named test_math.py with a simple function. In pytest, a test is just a function whose name starts with test_. Use plain assert statements to check expected outcomes:
def add(a, b):
return a + b
def test_add():
assert add(2, 3) == 5
assert add(0, 0) == 0
Group Related Tests with Classes
While standalone functions work well, grouping tests in a class helps organize related test cases. In pytest, any class beginning with Test will collect its test_ methods:
class TestCalculator:
def test_add(self):
assert add(2, 3) == 5
def test_subtract(self):
assert subtract(5, 2) == 3
Use Fixtures for Setup and Teardown
Fixtures are reusable pieces of setup code that prepare data or objects your tests need. Define a fixture with the @pytest.fixture decorator and inject it into your test function as a parameter:
@pytest.fixture
def sample_list():
return [1, 2, 3]
def test_length(sample_list):
assert len(sample_list) == 3
Run Your Tests Easily
Execute all tests by running pytest in the terminal. It automatically finds test files, runs each test, and reports which passed or failed. Add -v for verbose output, or use pytest test_math.py::test_add to run a single test. These fast feedback loops make unit testing painless and effective.
Start small: write tests for new functions you create, and gradually cover existing code. Solid unit tests give you the confidence to build bigger features without breaking what already works.