The CheckOps Engineer
pytest
pytest is the usual Python test runner: plain asserts, fixtures, parametrization, and a large plugin set.
Latest public signals
Not refreshed yet. Refresh reads the public site and, when the entry has a GitHub repository, the latest release.
Introduction
pytest is the test runner most Python projects use. You write functions named test_*, use the language’s assert, and pytest rewrites those asserts so failures show the values involved. Setup and teardown live in fixtures, which tests request by naming a parameter. The core project is MIT-licensed at pytest-dev/pytest.
The runner collects tests from files, classes, and directories, then runs them in one process by default. Plugins add parallel runs, coverage, Django and Flask integration, asyncio, and random order. pytest does not drive a browser or a mobile device by itself. Those are separate plugins or other tools.
Features
- Assert rewriting: A failing
assert response.status_code == 200prints both sides. You do not callself.assertEqual. - Fixtures: A fixture in
conftest.pyor a test module is injected by parameter name. Scope can be function, class, module, package, or session. - Parametrize:
@pytest.mark.parametrizeruns one test body against a table of inputs and expected values. - Markers:
@pytest.mark.slowand custom markers select or skip tests from the command line (-m "not slow"). - Plugins:
pytest-xdistruns workers in parallel.pytest-covreports coverage. Framework plugins load app fixtures. - Fixtures as resources:
tmp_path,monkeypatch,capsys, andcapfdare built in. Third-party fixtures start databases and HTTP servers. - Output: Short tracebacks, a summary of failures, and
--junitxmlfor CI.-kselects tests by name expression. - Doctest and unittest: pytest collects
unittest.TestCaseclasses and can run doctests, so older suites do not have to be rewritten on day one.
Pros
- Little boilerplate: A test is a function and an assert. New contributors can read a file without learning an assertion API.
- Fixtures compose: Database, client, and factory fixtures stack by name instead of a deep
setUpinheritance tree. - Plugin coverage: Django, Flask, asyncio, httpx, and hypothesis integrations already exist. You rarely write the glue yourself.
- Failure output is specific: Rewritten asserts and fixture scopes make the failing value and the setup that produced it visible.
- Free and standard: MIT-licensed, packaged on PyPI, and expected by Python CI templates.
Cons
- Fixture graphs get opaque: A test with five parameters hides where the database was created. Large
conftest.pyfiles are hard to trace. - Collection has a cost: Importing every test module runs top-level code. A slow import or a fixture with session scope can dominate a small change.
- Plugins conflict: Two plugins that both wrap
pytest_runtest_callfail in non-obvious ways. Pin versions. - Parallelism is not free:
pytest-xdistbreaks tests that share a process-wide resource unless they were written for it. - Not a system-test tool: Browser, mobile, and load tests need other runners. pytest can launch them, but it does not replace them.
Usage and Links (Example)
pip install pytest
pytest
pytest -k "login and not slow"
pytest --junitxml=report.xml
import pytest
def add(a, b):
return a + b
@pytest.mark.parametrize("a,b,expected", [(1, 2, 3), (0, 0, 0)])
def test_add(a, b, expected):
assert add(a, b) == expected
Put shared fixtures in conftest.py next to the tests that use them. A fixture is only instantiated when a test asks for it by name.
Resources:
Pricing
- Free: pytest is MIT-licensed and distributed on PyPI. There is no pytest company plan.
- Plugins are separate: Most plugins are also free. A few commercial Python tools wrap pytest; those prices are not pytest’s.
Recommended for?
- Python services and libraries that need unit and integration tests in the same runner.
- Django, Flask, and FastAPI projects that already have a pytest plugin for the app client and database.
- Data and ML code written in Python, including suites that call DeepEval or similar pytest-style evals.
- Teams migrating off
unittestwho want to keep existingTestCaseclasses while new tests use functions.
Conclusion
pytest is the Python runner to reach for unless a framework forces another one. Fixtures and parametrization cover most unit and service tests, and the plugin set covers the frameworks around them. Keep fixture scope explicit, and do not expect pytest alone to cover browser or device testing.