Skip to main content

assert-pytest-fixture-name-is-needed

Assert that every pytest fixture filed under a name of its own needs one.

Why

A name argument on a fixture decorator files that fixture under a name other than its function's, and there is one reason to write it. pylint objects when a name defined at the top of a module is bound again inside a function in it, and a test asks for a fixture by taking a parameter of the fixture's name, so renaming the function ends the clash.

Where nothing in the file binds that name there is no clash, and the argument costs twice over. Whoever has one file open copies it into the next, so the shape spreads. And it hides the fixture from every check that reads for the name of a function, which is how a fixture nothing calls any more stays in the tree: the check searches for the name of the function and never for the name a test asks for.

So this tool reads the argument as a claim about the file it sits in and checks it. A file whose fixtures all need their names passes silently.

Installation

pip install assert-pytest-fixture-name-is-needed

Usage

# Every test tree this repository publishes
assert-pytest-fixture-name-is-needed test

# The same, leaving out tests somebody else wrote
assert-pytest-fixture-name-is-needed test \
  --exclude 'test/vendor/*'

Options

Option Effect
--exclude PATTERNS Comma-separated globs to leave out.
--annotate Print each finding as a GitHub Actions ::error annotation.
--quiet Print nothing; report through the exit code.
--count Print only how many findings there were.
--verbose Print the files read, the findings and a summary.
--fail-fast Stop at the first finding.
--warn-only Always exit 0.

Exit codes

Code Meaning
0 Every filed name is needed
1 A filed name is needed by nothing
2 A tree was missing, unreadable, or would not parse

What counts as a fixture

A decorator that calls something named fixture, so @pytest.fixture, a plain @fixture imported from pytest, and the same factory a plugin re-exports are all read. A bare decorator with no call carries no argument to be needless and is left alone, as is a name computed rather than written out, which cannot be checked against anything.

A fixture filed under the name it already has is left alone too. The argument there is redundant whatever the file binds, so it says nothing about the bindings and this tool has nothing to report about it.

What counts as a binding

Every name bound anywhere below the top level of the file, because pylint objects to all of them alike:

Bound by Example
A parameter def test_x(config):
An assignment config = build()
A loop variable for config in rows:
A context manager target with open(p) as config:
A comprehension variable [config for config in rows]
A caught exception except KeyError as config:
An import from etc import config
A match capture case {"a": config}:
A nested definition def config():

The set has to be that wide. Narrowing it to parameters is the mistake this tool exists to stop somebody making: two helpers assigning a local named config beside a fixture filed as config are a real clash, and a tool that asked only about parameters would tell the next reader to rename the function and take two new pylint findings for it.

A comprehension and a lambda are scopes wherever they are written, so what they bind counts even at the top level of the file. Everything else written at the top level is the fixture's own neighbourhood rather than an inner scope, and binds nothing this tool counts.

What is walked

A directory argument is read recursively for *.py files. .git, __pycache__ and node_modules are skipped, and everything else you want left out goes in --exclude. Each file is read on its own and needs nothing from any other, so a single file is as valid an argument as a tree.

GitHub Actions

- name: Assert every fixture name is needed
  uses: 10U-Labs/assert-pytest-fixture-name-is-needed@latest
  with:
    trees: test

annotate defaults to true there, so each finding lands on the line it names in the diff.

License

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_name_is_needed-20260825093937.tar.gz.

File metadata

File hashes

Hashes for assert_pytest_fixture_name_is_needed-20260825093937.tar.gz
Algorithm Hash digest
SHA256 f657a0c77589896bb47829507bdbed9521861735ae594bd512b70445349ad2fc
MD5 c84b9e7d374ebd5717f32a43374d354b
BLAKE2b-256 13e648fcf9d087111c659da4ac6cd673a3fb0d74544720d1d5dedaed239c34a8

See more details on using hashes here.

Provenance

The following attestation bundles were made for assert_pytest_fixture_name_is_needed-20260825093937.tar.gz:

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

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_name_is_needed-20260825093937-py3-none-any.whl.

File metadata

File hashes

Hashes for assert_pytest_fixture_name_is_needed-20260825093937-py3-none-any.whl
Algorithm Hash digest
SHA256 81dc4faa51d280dc8ff700b3010c813db571623aefb7c9f1bf8a50f73d4beeb3
MD5 c3b2e8e6f01a45cb79d64592a6d42967
BLAKE2b-256 8000a7cb1e4bd0d3d9af3d1231748bcb6079cd0a2db302fb0c6dcb71d33a7320

See more details on using hashes here.

Provenance

The following attestation bundles were made for assert_pytest_fixture_name_is_needed-20260825093937-py3-none-any.whl:

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

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

Release history Release notifications | RSS feed

20260830060105

2 files

This release

20260825093937 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