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__.pyAdding 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 / bCreating 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)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
Configuring Pytest
Now let’s customize the default options when running pytest.
Add the following to your pyproject.toml file:
[tool.pytest.ini_options]
addopts = "--maxfail=1 --cov=testing_demo"Now re-run pytest on the command line. It will automatically be run with these options set:
- --maxfail=1stop after the first failure
- --cov=testing_demogenerates the coverage report