| name | pytest-mastery |
| description | Python testing with pytest using uv package manager. Use when: (1) Running Python tests, (2) Writing test files or test functions, (3) Setting up fixtures, (4) Parametrizing tests, (5) Generating coverage reports, (6) Testing FastAPI applications, (7) Debugging test failures, (8) Configuring pytest options. Triggers: "run tests", "write tests", "test coverage", "pytest", "unit test", "integration test", "test FastAPI".
|
pytest Testing with uv
Quick Reference
uv run pytest
uv run pytest -v
uv run pytest tests/test_example.py
uv run pytest tests/test_example.py::test_function_name
uv run pytest -k "pattern"
uv run pytest --cov=src --cov-report=html
Installation
uv add --dev pytest
uv add --dev pytest-cov
uv add --dev pytest-asyncio httpx
Test Discovery
pytest automatically discovers tests following these conventions:
- Files:
test_*.py or *_test.py
- Functions:
test_*
- Classes:
Test* (no __init__ method)
- Methods:
test_* inside Test* classes
Standard project structure:
project/
├── src/
│ └── myapp/
├── tests/
│ ├── __init__.py
│ ├── conftest.py # Shared fixtures
│ ├── test_unit.py
│ └── integration/
│ └── test_api.py
└── pyproject.toml
Fixtures
Fixtures provide reusable test setup/teardown:
import pytest
@pytest.fixture
def sample_user():
return {"id": 1, "name": "Test User"}
@pytest.fixture
def db_connection():
conn = create_connection()
yield conn
conn.close()
def test_user_name(sample_user):
assert sample_user["name"] == "Test User"
Fixture Scopes
@pytest.fixture(scope="function")
@pytest.fixture(scope="class")
@pytest.fixture(scope="module")
@pytest.fixture(scope="session")
Shared Fixtures (conftest.py)
Place in tests/conftest.py for automatic availability:
import pytest
@pytest.fixture
def api_client():
return TestClient(app)
Parametrization
Run same test with multiple inputs:
import pytest
@pytest.mark.parametrize("input,expected", [
(1, 2),
(2, 4),
(3, 6),
])
def test_double(input, expected):
assert input * 2 == expected
@pytest.mark.parametrize("value", [None, "", [], {}])
def test_falsy_values(value):
assert not value
Common Options
| Option | Description |
|---|
-v | Verbose output |
-vv | More verbose |
-q | Quiet mode |
-x | Stop on first failure |
--lf | Run last failed tests only |
--ff | Run failures first |
-k "expr" | Filter by name expression |
-m "mark" | Run marked tests only |
--tb=short | Shorter traceback |
--tb=no | No traceback |
-s | Show print statements |
--durations=10 | Show 10 slowest tests |
-n auto | Parallel execution (pytest-xdist) |
Coverage Reports
uv run pytest --cov=src
uv run pytest --cov=src --cov-report=html
uv run pytest --cov=src --cov-fail-under=80
uv run pytest --cov=src --cov-report=term --cov-report=xml
Markers
import pytest
@pytest.mark.slow
def test_slow_operation():
...
@pytest.mark.skip(reason="Not implemented")
def test_future_feature():
...
@pytest.mark.skipif(condition, reason="...")
def test_conditional():
...
@pytest.mark.xfail(reason="Known bug")
def test_known_failure():
...
Run by marker:
uv run pytest -m "not slow"
uv run pytest -m "integration"
pyproject.toml Configuration
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_functions = ["test_*"]
addopts = "-v --tb=short"
markers = [
"slow: marks tests as slow",
"integration: integration tests",
]
[tool.coverage.run]
source = ["src"]
omit = ["tests/*", "*/__init__.py"]
[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"if TYPE_CHECKING:",
]
FastAPI Testing
See references/fastapi-testing.md for comprehensive FastAPI testing patterns including:
- TestClient setup
- Async testing with httpx
- Database fixture patterns
- Dependency overrides
- Authentication testing
Debugging Failed Tests
uv run pytest --tb=long
uv run pytest --pdb
uv run pytest -l
uv run pytest --lf