Setting up testing with pytest and uv
This tutorial guides you through setting up a testing environment using pytest with uv for Python projects. You’ll learn how to create a project with tests, run them efficiently, and implement testing best practices.
Prerequisites
Creating a Project with Tests
Let’s start by creating a sample project with a test directory structure:
$ uv init testing-demo --package
$ cd testing-demo
This creates a Python package project with the following structure:
testing-demo/
├── pyproject.toml
├── README.md
└── src
└── testing_demo
└── __init__.py
Adding pytest as a Development Dependency
Add pytest to your project’s development dependencies:
$ uv add --dev pytest
This command:
- Updates your pyproject.toml with pytest as a development dependency
- Creates the project’s lockfile
- Installs pytest in your project’s virtual environment
Creating a Simple Module to Test
Let’s create a simple calculator module to test. Create a new file at src/testing_demo/calculator.py
:
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def multiply(a, b):
return a * b
def divide(a, b):
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
Creating Test Files
Create a tests
directory at the root of your project:
$ mkdir tests
Now, create a test file for our calculator module in tests/test_calculator.py
:
import pytest
from testing_demo.calculator import add, subtract, multiply, divide
def test_add():
assert add(1, 2) == 3
assert add(-1, 1) == 0
assert add(-1, -1) == -2
def test_subtract():
assert subtract(3, 2) == 1
assert subtract(2, 3) == -1
assert subtract(0, 0) == 0
def test_multiply():
assert multiply(2, 3) == 6
assert multiply(-2, 3) == -6
assert multiply(-2, -3) == 6
def test_divide():
assert divide(6, 3) == 2
assert divide(6, -3) == -2
assert divide(-6, -3) == 2
def test_divide_by_zero():
with pytest.raises(ValueError):
divide(5, 0)
Configuring pytest
Let’s configure pytest in your pyproject.toml
file by adding these settings:
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = "test_*.py"
python_functions = "test_*"
This configuration:
- Sets the test discovery path to the
tests
directory - Specifies that test files should start with
test_
- Specifies that test functions should start with
test_
Running Tests
Now you can run your tests using uv:
$ uv run pytest
To see more detailed output, use the verbose flag:
$ uv run pytest -v
Adding Test Coverage
Let’s add coverage reporting to see how much of our code is tested:
$ uv add --dev pytest-cov
Now run tests with coverage:
$ uv run pytest --cov=testing_demo
For a more detailed report:
$ uv run pytest --cov=testing_demo --cov-report=term-missing