pytest Setup
pytest discovers and runs tests by convention - no boilerplate test classes required. A tests/ directory, a pyproject.toml config block, and uv add --group dev pytest is enough to start.
Search across all documentation pages
pytest discovers and runs tests by convention - no boilerplate test classes required. A tests/ directory, a pyproject.toml config block, and uv add --group dev pytest is enough to start.
uv add --group dev pytest
mkdir tests[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]uv run pytestWhen to reach for this:
unittest to pytestsrc/ layoutmyapp/
├── pyproject.toml
├── src/myapp/core.py
└── tests/
├── conftest.py
└── test_core.py
# tests/test_core.py
from myapp.core import add
def test_add():
assert add(2, 3) == 5[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]
addopts = "-ra -q"
filterwarnings = ["error"]uv run pytest -v
uv run pytest tests/test_core.py::test_addWhat this demonstrates:
tests/, named test_*.pypythonpath = ["src"] enables imports without editable install in simple setupsconftest.py holds shared fixturesaddopts sets default CLI flags for every runtest_*.py or *_test.pytest_*Test* (no __init__)pytest-asyncio for async tests)| File | Priority |
|---|---|
pyproject.toml [tool.pytest.ini_options] | Preferred |
pytest.ini | Legacy |
conftest.py hooks | Per-directory |
testpaths = ["tests"] limits discovery.ModuleNotFoundError. Fix: pythonpath = ["src"] or pip install -e ..pytest: command not found. Fix: uv sync --group dev or uv run pytest.conftest.py fixtures - name collisions across directories. Fix: scope fixtures carefully; use unique names.filterwarnings = ["error"] to fail on unexpected warnings.| Alternative | Use When | Don't Use When |
|---|---|---|
| unittest | Stdlib only, no deps | You want fixtures and plugins |
| nose2 | Legacy nose migration | New projects |
| behave | BDD acceptance tests | Unit/integration tests |
tests/ at project root is the convention. Mirror src/ structure inside it.
No for pytest 7+. Empty tests/ without __init__.py works fine.
pytest tests/test_core.py::test_add or pytest -k "add".
Shared fixtures and hooks. Loaded automatically from test directory up to root.
@pytest.mark.skip(reason="...") or @pytest.mark.skipif(condition, reason="...").
Yes. pytest collects unittest.TestCase subclasses automatically.
pytest -s disables output capture.
Default CLI arguments applied to every pytest invocation.
markers = ["slow: marks slow tests"] in config; register all custom markers.
pytest for new projects. Richer fixtures, plugins, and less boilerplate.
Stack versions: This page was written for Python 3.14.0, FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 19, 2026