Skip to main content

assert-pytest-fixture-is-requested

Assert that every pytest fixture is asked for by something.

A fixture runs only when something asks for it. Delete the last test that asks, and the fixture stays: it is collected into every session that loads its file, the tests written for it keep passing, and the coverage gate on its package stays green. Nothing shows the requester has gone.

A check that matches the fixture's name against the source cannot answer this. A fixture's name is an ordinary identifier that anything else may bind, so a local variable credits it and so does an unrelated function of the same name. Worse, matching a name cannot tell which definition a request resolves to, and it counts a request written inside a factory that nothing ever calls.

So this tool asks pytest. It runs a real collection, reads the fixtures off it, and adds the one thing a collection cannot see: getfixturevalue.

What counts as asking

pytest resolves five of the six ways itself, and the collection reports them:

  • a test function taking the fixture as a parameter
  • another fixture taking it as a parameter
  • a pytest.mark.usefixtures mark naming it as a string
  • a request.getfixturevalue call naming it as a string
  • autouse=True, which asks on every in-scope test's behalf

The sixth is a request.getfixturevalue call on a variable, where the name arrives from somewhere else:

def create_log_group_tests(log_group_fixture: str) -> type:
    class TestLogGroup:
        def test_retention(self, request):
            log_group = request.getfixturevalue(log_group_fixture)

Following that argument back to its call sites is interprocedural analysis. This tool takes the blunt instrument instead: where a getfixturevalue call is handed anything but a string literal, every string constant anywhere in the trees counts as a possible request. That over-credits — a dictionary key spelled like a fixture will spare a dead one — and the miss is the right way to be wrong, since a fixture wrongly kept costs a line and a fixture wrongly deleted costs a red suite. It degrades to nothing where a repository makes no such call.

Why a collection rather than a parse

Two things only pytest knows.

Which definition a request resolves to. Where conftests at two levels publish the same fixture name, pytest hands each item the one visible to it. A name match credits both, so a definition that every requester shadows looks alive.

Whether the asking is reachable. A parameter of a test method inside a factory nothing calls is not a request, because the class is never built and the method never becomes a test.

Install

pip install assert-pytest-fixture-is-requested

Use

assert-pytest-fixture-is-requested test lib

The trees are collected and read. Because the tool runs a real pytest collection, it must run where the target's tests import: install the test dependencies and set PYTHONPATH as the suite expects.

Options

  • --defined-in TREE — a tree the own-tests exclusion applies to. Repeatable.
  • --dont-search-in PATTERN — a path whose requests do not credit a fixture of the matching package, with {package} standing for the package name. Repeatable.
  • --import-mode MODE — the pytest import mode. Defaults to importlib, which reads a whole tree whose test files repeat a basename.
  • --rootdir PATH — the directory reported paths are expressed against. Defaults to the working directory.
  • --pytest-argument ARGUMENT — a further argument for the collection, such as --pytest-argument=--confcutdir=test. Repeatable.
  • --annotate — print each finding as a GitHub Actions error annotation.
  • --quiet, --count, --verbose — choose the output.
  • --fail-fast, --warn-only — stop at the first finding, or always exit 0.

The own-tests exclusion

A suite written to exercise a fixture asks for it, so crediting that suite makes every such fixture look used. Name the trees the exclusion applies to and the shape of the suite that does not count:

assert-pytest-fixture-is-requested test lib \
  --defined-in lib/python \
  --dont-search-in 'test/lib/python/test_{package}'

A fixture published from lib/python/<package>/ is then not credited by a request from test/lib/python/test_<package>/. A fixture defined under test/ is credited by a request from anywhere, its own file included, because the conftest that publishes it and the suite that asks for it are the same subtree by design.

Exit codes

  • 0 — every fixture is asked for
  • 1 — at least one fixture is asked for by nothing
  • 2 — a tree was missing, a file was unreadable, or the collection failed

A collection error exits 2 rather than 1, because a file that fails to import registers none of its requests and would make live fixtures look dead.

GitHub Actions

- uses: 10U-Labs/assert-pytest-fixture-is-requested@latest
  with:
    trees: test lib
    defined-in: lib/python
    dont-search-in: test/lib/python/test_{package}
    verbose: "true"

Limitations

  • The tool must run where the target's tests import cleanly.
  • A dynamic getfixturevalue call makes every string constant a possible request, which deliberately over-credits.
  • Fixtures registered by pytest itself and by installed plugins are ignored, because they are written outside the trees handed over.

Licence

Apache-2.0.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file assert_pytest_fixture_is_requested-20260907234601.tar.gz.

File metadata

File hashes

Hashes for assert_pytest_fixture_is_requested-20260907234601.tar.gz
Algorithm Hash digest
SHA256 6f14ccdd4ee54cf877a04ec0884678ee4372ad80d85c0a2a35c744452f0bee82
MD5 db29fe72b7283a2d4032c2e88fc033e2
BLAKE2b-256 a01dadb61e95b7878edf5419fccab5d0b0ad67da43dc777a072c445a21aada4c

See more details on using hashes here.

Provenance

The following attestation bundles were made for assert_pytest_fixture_is_requested-20260907234601.tar.gz:

Publisher: release.yml on 10U-Labs/assert-pytest-fixture-is-requested

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file assert_pytest_fixture_is_requested-20260907234601-py3-none-any.whl.

File metadata

File hashes

Hashes for assert_pytest_fixture_is_requested-20260907234601-py3-none-any.whl
Algorithm Hash digest
SHA256 005db39504f10b80a26e91e58873f891c8889cbc5d0cdc822c908e78175adf6b
MD5 742437dc0609a50b0268e6917e3f1a06
BLAKE2b-256 189d467ff93f26681295cb059f9ffde3397db3b13622a1066ca12d8b3274fa54

See more details on using hashes here.

Provenance

The following attestation bundles were made for assert_pytest_fixture_is_requested-20260907234601-py3-none-any.whl:

Publisher: release.yml on 10U-Labs/assert-pytest-fixture-is-requested

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

20260907234601 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page