Plugins and the Ecosystem
The plugin is the pytest-* package that registers hooks into the run: the pytest-cov (the coverage), the pytest-mock (the mocker fixture), the pytest-asyncio (the async test), the pytest-html (the HTML report), the pytest-xdist (the parallel), and the pytest-rerunfailures (the flaky's retry). The pip install pytest-* is the one command, the pytest --version lists the installed, and the -p no:plugin disables one without the uninstall. This chapter covers the install and the list, the popular plugins (the cov, the mock, the asyncio, the html, the xdist, the rerun), the -p enable/disable, and the conftest the project's local plugin.
The Install and the List
# the install: the single pytest-* package
pip install pytest-cov
pip install pytest-mock
pip install pytest-asyncio
pip install pytest-html
pip install pytest-xdist
pip install pytest-rerunfailures
# the the dev extra (the the requirements.txt):
# pytest, the pytest-cov, the pytest-mock, the
# pytest-asyncio, the pytest-html, the pytest-xdist
# the list: the INSTALLED plugins
pytest --version
# pytest 8.x.x
# plugins: cov-5.x, html-4.x, mock-3.x,
# asyncio-0.x, xdist-3.x
# the -VV: the per-plugin hook list (the deep
# inspect of what each plugin registers)
The install is the per-plugin: each pytest-* is a separate package, and the project's [dev] extra (or the requirements-dev.txt) lists the set the team shares, so the pip install -e ".[dev]" gives the whole environment. The pytest --version lists the installed plugins (the plugins: cov-5.x, html-4.x, ... line), and the -VV adds the per-plugin hook list (the deep inspect of what each registers). The -p no:cov disables one for the run (the -p no:xdist the no-parallel when the flaky is the xdist's), and the -p no:randomly the no-shuffle when the order matters - the disable is the run's, the uninstall is the environment's, and the next section's catalog is the plugins the suite actually uses.
The Popular Plugins
# the COVERAGE: the pytest-cov (the --cov)
pytest --cov=texttools --cov-report=term-missing
# the MOCK: the pytest-mock (the mocker fixture,
# the no-decorator patch)
def test_x(mocker):
w = mocker.patch("texttools.io.write_file")
# the ASYNC: the pytest-asyncio (the asyncio mark)
@pytest.mark.asyncio
async def test_async(): ...
# the HTML: the pytest-html (the report)
pytest --html=report/report.html --self-contained-html
# the PARALLEL: the pytest-xdist (the CPU's workers)
pytest -n auto
pytest -n 4 --dist=loadfile # the per-file split
# the RERUN: the pytest-rerunfailures (the flaky)
pytest --reruns 2 # the retry 2 times on fail
The catalog is the six the suite uses: the pytest-cov adds the --cov (the measurement, the report, the fail-under gate), the pytest-mock adds the mocker fixture (the no-decorator patch, the auto-restore), the pytest-asyncio adds the @pytest.mark.asyncio (the async test, the async fixture, the asyncio_mode), the pytest-html adds the --html (the self-contained report), the pytest-xdist adds the -n (the parallel, the loadfile the per-file split so the fixture state stays within the worker), and the pytest-rerunfailures adds the --reruns 2 (the flaky's retry, the transient's no-fail). The pytest-randomly (the shuffle) and the pytest-timeout (the --timeout the hung test's killer) are the two the CI adds. The rule is the one: the plugin is the pytest-* the pip installs, the --version the list, the -p no:name the run's disable, and the conftest (the next section) is the project's local plugin without the install.
The conftest: The Local Plugin
# the conftest.py: the LOCAL plugin (the no-install,
# the project's own hooks)
import pytest
def pytest_configure(config):
# the START (the project's setup, the config's
# the object)
config._texttools_root = "texttools"
def pytest_collection_modifyitems(items):
# the COLLECTED list (the sort, the filter, the
# the order the run takes)
items.sort(key=lambda i: i.name)
def pytest_terminal_summary(terminalreporter):
# the END (the project's note, the line)
terminalreporter.write_line(
"the suite covered the texttools")
The conftest.py is the local plugin: the pytest_configure hook runs at the start (the project's setup, the config the object), the pytest_collection_modifyitems reshapes the collected list (the sort, the filter, the order), and the pytest_terminal_summary adds the line at the end (the project's note). The no pip install, the no pytest-* name - the hook functions in the conftest register automatically, and the next chapter's hooks detail the full surface (the pytest_runtest_setup, the pytest_runtest_makereport, the pytest_sessionfinish) the conftest and the installed plugin both use.
The Working Rules
- The plugin is the
pytest-*package, thepipthe install. The[dev]extra the team's set, thepytest --versionthe installed list, the-VVthe per-plugin hooks, and the-p no:namethe run's disable (the-p no:xdistthe no-parallel). - The six are the suite's: the cov, the mock, the asyncio, the html, the xdist, the rerun. The
--covthe measure, themockerthe fixture, the@pytest.mark.asynciothe async, the--htmlthe report, the-n autothe parallel, the--reruns 2the flaky's retry - plus therandomlyand thetimeoutthe CI adds. - The
-nis the parallel, theloadfilethe per-file split. The-n autothe CPU's workers, the--dist=loadfilethe file stays in one worker (the session fixture the no cross-worker), and the hung test's killer is thepytest-timeoutthe--timeout. - The
conftestis the local plugin, the no install. Thepytest_configure, thepytest_collection_modifyitems, thepytest_terminal_summarythe hook functions theconftestregisters - the project's customization without thepytest-*package.
Summary
The plugin is the pytest-* package that registers hooks into the run: the pip install pytest-* the one command, the pytest --version the installed list, the -VV the per-plugin hooks, and the -p no:name the run's disable. The catalog is the six the suite uses (the pytest-cov the --cov, the pytest-mock the mocker, the pytest-asyncio the async mark, the pytest-html the --html, the pytest-xdist the -n parallel with the loadfile split, the pytest-rerunfailures the --reruns), plus the randomly and the timeout the CI adds. The conftest.py is the local plugin (the pytest_configure, the pytest_collection_modifyitems, the pytest_terminal_summary the hook functions, the no install), and the next chapter's hooks detail the full surface the conftest and the installed plugin both register.