Skillversitas

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, the pip the install. The [dev] extra the team's set, the pytest --version the installed list, the -VV the per-plugin hooks, and the -p no:name the run's disable (the -p no:xdist the no-parallel).
  • The six are the suite's: the cov, the mock, the asyncio, the html, the xdist, the rerun. The --cov the measure, the mocker the fixture, the @pytest.mark.asyncio the async, the --html the report, the -n auto the parallel, the --reruns 2 the flaky's retry - plus the randomly and the timeout the CI adds.
  • The -n is the parallel, the loadfile the per-file split. The -n auto the CPU's workers, the --dist=loadfile the file stays in one worker (the session fixture the no cross-worker), and the hung test's killer is the pytest-timeout the --timeout.
  • The conftest is the local plugin, the no install. The pytest_configure, the pytest_collection_modifyitems, the pytest_terminal_summary the hook functions the conftest registers - the project's customization without the pytest-* 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.