Skip to main content

pytest-autofixture

Use pytest fixtures by bare name. Tests and fixtures can reference any fixture without declaring it as a function parameter.

Install

pip install pytest-autofixture

Requires Python 3.11+ and pytest 8.4+. The plugin is active once installed; turn it off for a run with -p no:autofixture.

Usage

Any name in a test or fixture body that would otherwise raise NameError is looked up as a fixture. Lookup is lazy, so a fixture is set up only if the code reaches it, and scope, overrides and teardown work as they do for declared fixtures. Declared parameters still work and mix freely with bare names.

Fixtures resolve their dependencies from where the test is, so an inner class can override one value and outer fixtures pick it up, like a nested let in RSpec:

@pytest.fixture
def role():
    return "member"


@pytest.fixture
def user():
    return User(role=role)


def test_member():
    assert not user.can_delete()


class TestAdmin:
    @pytest.fixture
    def role(self):
        return "admin"

    def test_admin(self):
        assert user.can_delete()

parametrize needs no declaration either:

@pytest.mark.parametrize("role", ["admin", "owner"])
def test_can_delete():
    assert user.can_delete()

A parametrized name belongs to the test, like an argument, so in the test body it beats a builtin or module global of the same name: parametrize("input", ...) is fine. Fixture bodies keep the real builtin or global.

let

let defines a one-line fixture where it's written, at module level or in a test class, like RSpec's let(:role) { "member" }:

from pytest_autofixture import let

let.role = "member"
let.user = lambda: User(role=role)


class TestAdmin:
    let.role = "admin"

    def test_admin(self):
        assert user.can_delete()

What you assign decides how it behaves:

  • A lambda is called on first use, at most once per test, and can use other fixtures by bare name.
  • Anything else is deep-copied for each test, so let.items = [] or let.user = User() starts fresh every time. Strings, numbers, classes and functions pass through as-is (let.model = User is the class itself). If a value can't be copied, or must stay one shared object, use a lambda.

A let in a class overrides a fixture of the same name from outside it or from a base class, and can build on the value it replaces, like RSpec's super(): let.role = lambda: role.upper() gets the outer role.

let raises TypeError on the spot for a lambda with parameters, a value that can't be copied, or a name already taken by a builtin or module global, such as let.id or let.json after import json (the other name would always win).

Use a regular fixture when you need more than one expression, a scope, params or teardown. There's no special subject: let.subject = lambda: Order(items=items) is just a fixture named subject.

Coming from RSpec

RSpec pytest-autofixture
let(:user) { User.new(role:) } let.user = lambda: User(role=role)
let! / before @pytest.fixture(autouse=True) (not setup_method, which can't see bare names)
after a yield fixture
subject let.subject = lambda: ...
describe / context a nested class, named Test... so pytest collects it
shared_examples a base test class
same examples with a different let @pytest.mark.parametrize("role", [...])

Limitations

Declare the fixture as a parameter instead when:

  • the test is wrapped by a decorator such as @mock.patch or hypothesis's @given, or by a plugin (the test fails with an error saying so)
  • the fixture is parametrized
  • an async test uses an async fixture
  • a yield fixture first uses the name after its yield (pytest 9.1+ refuses fixture lookups during teardown)

Only test and fixture bodies see bare names; a module-level helper raises NameError, so pass the value in. Inside a test, globals() isn't the module's dict (use sys.modules[__name__]), a global write reaches the module only when the test returns, and del of a global fails.

Linters flag bare fixture names as undefined (ruff F821, pyright). Silence that for test files, e.g. in pyproject.toml:

[tool.ruff.lint.per-file-ignores]
"tests/**" = ["F821"]

installs

Metadata

Release files for pytest-autofixture 0.3.1

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

Source distribution (sdist)

Source distribution for pytest-autofixture 0.3.1
File Size Uploaded Provenance Actions
pytest_autofixture-0.3.1.tar.gz 12.4 kB With provenance Details for pytest_autofixture-0.3.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pytest-autofixture 0.3.1
File Interpreter ABI Platform Actions
pytest_autofixture-0.3.1-py3-none-any.whl Python 3 none any Details for pytest_autofixture-0.3.1-py3-none-any.whl

Total release size: 21.3 kB

Release files / pytest_autofixture-0.3.1.tar.gz

Download URL pytest_autofixture-0.3.1.tar.gz
Size 12.4 kB
Tags Source
SHA-256 checksum
How to use checksums
71dc07773ebbf9eb029fa8725d829b2e26cf179e039777b66ade01e93cadf107
BLAKE2b-256 checksum
How to use checksums
ed201e9b4e89a285c4714588f2ba96a597538405b64eb74d5a51ba733804f590
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 27, 2026.

Transparency log

Release files / pytest_autofixture-0.3.1-py3-none-any.whl

Download URL pytest_autofixture-0.3.1-py3-none-any.whl
Size 8.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
615d9d6b1eae19c02b901cc3375ba624798197aff97c7c22a8ecadf8106a026b
BLAKE2b-256 checksum
How to use checksums
35efa08a0679d47b67132b0a7aaa7bf7f4cff4382481f8adce29a59845cccf8e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 27, 2026.

Transparency log

Security for pytest-autofixture 0.3.1

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

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pytest_autofixture-0.3.1.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 Oct 27, 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