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

Metadata

Release files for assert-pytest-fixture-name-is-needed 20260825093937

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for assert-pytest-fixture-name-is-needed 20260825093937
File Size Uploaded Provenance
assert_pytest_fixture_name_is_needed-20260825093937.tar.gz 34.3 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for assert-pytest-fixture-name-is-needed 20260825093937
File Interpreter ABI Platform
assert_pytest_fixture_name_is_needed-20260825093937-py3-none-any.whl Python 3 none any Details

Total release size: 49.4 kB

Release files / assert_pytest_fixture_name_is_needed-20260825093937.tar.gz

Download URL assert_pytest_fixture_name_is_needed-20260825093937.tar.gz
Size 34.3 kB
Tags Source
SHA-256 checksum
How to use checksums
f657a0c77589896bb47829507bdbed9521861735ae594bd512b70445349ad2fc
BLAKE2b-256 checksum
How to use checksums
13e648fcf9d087111c659da4ac6cd673a3fb0d74544720d1d5dedaed239c34a8
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 25, 2026.

Transparency log

Release files / assert_pytest_fixture_name_is_needed-20260825093937-py3-none-any.whl

Download URL assert_pytest_fixture_name_is_needed-20260825093937-py3-none-any.whl
Size 15.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
81dc4faa51d280dc8ff700b3010c813db571623aefb7c9f1bf8a50f73d4beeb3
BLAKE2b-256 checksum
How to use checksums
8000a7cb1e4bd0d3d9af3d1231748bcb6079cd0a2db302fb0c6dcb71d33a7320
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 25, 2026.

Transparency log

Security for assert-pytest-fixture-name-is-needed 20260825093937

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.

Select from 2 files

Attestation for assert_pytest_fixture_name_is_needed-20260825093937.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 25, 2026.

Transparency log

A 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.

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