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
Metadata
Release files for assert-pytest-fixture-name-is-needed 20260830060105
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| assert_pytest_fixture_name_is_needed-20260830060105.tar.gz | 34.3 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| assert_pytest_fixture_name_is_needed-20260830060105-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 49.4 kB
Release files / assert_pytest_fixture_name_is_needed-20260830060105.tar.gz
| Download URL | assert_pytest_fixture_name_is_needed-20260830060105.tar.gz |
|---|---|
| Size | 34.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
69589958db9cce6157b0674891ba040c61ff02f3d9706a069e3e2056a9a02580
|
|
BLAKE2b-256 checksum How to use checksums |
a488db6bf425f46298f8183a919f08cf646705557ec9aa5156adfe7afdac5014
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 30, 2026.
Transparency logRelease files / assert_pytest_fixture_name_is_needed-20260830060105-py3-none-any.whl
| Download URL | assert_pytest_fixture_name_is_needed-20260830060105-py3-none-any.whl |
|---|---|
| Size | 15.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
84d4128129a704923f8449381023657946b125da4ffa82e047fcac04509c65ce
|
|
BLAKE2b-256 checksum How to use checksums |
e8ddf0ae96f73a1dabbe5cd60107bb616dc7fb4419e97469ded6867bd752850b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 30, 2026.
Transparency logSecurity for assert-pytest-fixture-name-is-needed 20260830060105
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for assert_pytest_fixture_name_is_needed-20260830060105.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 30, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.