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
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file assert_pytest_fixture_name_is_needed-20260830060105.tar.gz.
File metadata
- Download URL: assert_pytest_fixture_name_is_needed-20260830060105.tar.gz
- Upload date:
- Size: 34.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69589958db9cce6157b0674891ba040c61ff02f3d9706a069e3e2056a9a02580
|
|
| MD5 |
682483d2efc1e50a0c6ec4bebc6a7870
|
|
| BLAKE2b-256 |
a488db6bf425f46298f8183a919f08cf646705557ec9aa5156adfe7afdac5014
|
Provenance
The following attestation bundles were made for assert_pytest_fixture_name_is_needed-20260830060105.tar.gz:
Publisher:
release.yml on 10U-Labs/assert-pytest-fixture-name-is-needed
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
assert_pytest_fixture_name_is_needed-20260830060105.tar.gz -
Subject digest:
69589958db9cce6157b0674891ba040c61ff02f3d9706a069e3e2056a9a02580 - Sigstore transparency entry: 2647775128
- Sigstore integration time:
-
Permalink:
10U-Labs/assert-pytest-fixture-name-is-needed@8036168d71d1436b1adedeaf677ec187a1a63616 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/10U-Labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8036168d71d1436b1adedeaf677ec187a1a63616 -
Trigger Event:
push
-
Statement type:
File details
Details for the file assert_pytest_fixture_name_is_needed-20260830060105-py3-none-any.whl.
File metadata
- Download URL: assert_pytest_fixture_name_is_needed-20260830060105-py3-none-any.whl
- Upload date:
- Size: 15.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
84d4128129a704923f8449381023657946b125da4ffa82e047fcac04509c65ce
|
|
| MD5 |
687c0e8efca84f5f30d4215c0cb03abd
|
|
| BLAKE2b-256 |
e8ddf0ae96f73a1dabbe5cd60107bb616dc7fb4419e97469ded6867bd752850b
|
Provenance
The following attestation bundles were made for assert_pytest_fixture_name_is_needed-20260830060105-py3-none-any.whl:
Publisher:
release.yml on 10U-Labs/assert-pytest-fixture-name-is-needed
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
assert_pytest_fixture_name_is_needed-20260830060105-py3-none-any.whl -
Subject digest:
84d4128129a704923f8449381023657946b125da4ffa82e047fcac04509c65ce - Sigstore transparency entry: 2647775154
- Sigstore integration time:
-
Permalink:
10U-Labs/assert-pytest-fixture-name-is-needed@8036168d71d1436b1adedeaf677ec187a1a63616 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/10U-Labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8036168d71d1436b1adedeaf677ec187a1a63616 -
Trigger Event:
push
-
Statement type: