Resource library

QA How-To

How to Fix pytest "fixture not found"

Fix pytest fixture not found by checking names, conftest.py visibility, plugins, CI environments, and dependencies with focused commands that prove the repair.

20 min read | 3,124 words

TL;DR

Inspect the missing name with `python -m pytest --fixtures <failing-test>`; correct its decorator, registered name, conftest.py location, or plugin installation. Then run that exact test under the same interpreter and environment that failed.

Key Takeaways

  • Target the exact failing test when listing available fixtures.
  • Register functions with @pytest.fixture before requesting them by parameter name.
  • Move shared conftest.py fixtures to the nearest common ancestor of their tests.
  • Install and load plugin fixtures in the same interpreter that runs pytest.
  • Trace missing fixture dependencies and indirect parameters before changing an outer test.
  • Verify with a focused test in the environment that failed, then run the suite.

Fix pytest fixture not found when it appears during test setup: a test or another fixture requests a name pytest cannot find in that test's visible fixture set. Read the missing name and the available-fixtures list before changing imports or installing packages.

E       fixture 'sample_payload' not found
>       available fixtures: capfd, caplog, monkeypatch, tmp_path, ...

The available list varies by project. The quoted name is the immediate failure, even when the stack trace points elsewhere. Fixtures live in test modules, applicable conftest.py files, or loaded plugins. Python importability alone does not publish them.

TL;DR

Find the test that asks for the missing name. Run python -m pytest --fixtures tests/test_example.py -q from the project root, replacing the path with the failing file. If the name is absent, check its spelling, @pytest.fixture decorator, and whether its conftest.py is in the test's directory or an ancestor. If the name belongs to a plugin, check the plugin in the same Python environment that invokes pytest. Then rerun the one failing test before the full suite.

python -m pytest --version
python -m pytest --fixtures tests/test_example.py -q
python -m pytest tests/test_example.py -q

The commands above assume tests/test_example.py exists in your project. Substitute your actual failing path; the later examples use a fresh tests/ directory and provide their own files. --fixtures is an inventory, not an assertion that a fixture's setup succeeds. The pytest beginner tutorial covers the test runner basics if collection itself is unfamiliar.

What the Error Actually Means

pytest resolves each fixture name for the individual collected test. It looks in that test's class or module, applicable conftest.py files up its directory tree, and loaded plugins. A fixture in a sibling test module is not available by name to this test. Likewise, a fixture in tests/api/conftest.py is visible to tests under tests/api/, but not to tests/ui/. The pytest fixture reference explains this visibility model.

The message is a lookup failure, not proof that a fixture's code ran and failed. If the fixture is found but raises during setup, pytest reports an exception from setup instead. If the test body makes an ordinary Python call to an undefined name, Python raises NameError; fixture injection did not happen because the name was not requested as a parameter or through request.getfixturevalue. Separate these cases before editing a working fixture.

The line shown in the stack trace may name a dependent fixture. For example, test_report(report) requests report, but if report asks for sample_payload and that dependency is absent, the reported missing name is sample_payload. The available fixtures list and --fixtures-per-test output reveal the graph. For a deeper model of fixture reuse in Python browser suites, see Playwright Python fixtures with pytest.

Root-Cause Decision Table

Symptom Root cause Fix
Name is absent and the function has no decorator Plain helper function, not a fixture Add @pytest.fixture and request its registered name
Fixture exists in a sibling directory conftest.py visibility boundary Move a genuinely shared fixture to a common ancestor
Fixture exists in a helper module but never appears in --fixtures Module was imported only as Python code Register it as a plugin or expose the fixture in conftest.py
mocker or another plugin fixture is absent Plugin missing, blocked, or installed elsewhere Install and load the plugin in the active interpreter
Local run passes, CI fails Different interpreter, dependency set, or test path Reproduce the job's interpreter and inspect plugin loading
Test requests account but decorator names user_record Registered name differs from requested name Match the test parameter to the fixture's public name
A fixture is listed, yet setup reports a different missing fixture Dependency inside the fixture is unresolved Define or register the dependency at the test's location
Only an indirect parametrized test fails Parametrized parameter has no fixture Define the parameter fixture or remove indirect=True

Use the command under each fix to prove visibility and run the focused test. Avoid rearranging the suite for one typo. The same approach helps with CI/CD troubleshooting for QA.

1. Fix pytest fixture not found when the function is not registered

A plain function called sample_payload is just a Python function. pytest does not inject its return value into a test parameter unless the function is registered as a fixture. The minimal repair is an import of pytest and its decorator. Save the following as tests/test_payload.py in a scratch project that has pytest installed:

# tests/test_payload.py
import pytest


@pytest.fixture
def sample_payload():
    return {"status": "ready", "count": 2}


def test_payload_has_count(sample_payload):
    assert sample_payload["status"] == "ready"
    assert sample_payload["count"] == 2

Verify it from the directory containing tests/:

python -m pytest tests/test_payload.py -q
python -m pytest --fixtures tests/test_payload.py -q

Expect one passing test and an entry named sample_payload in the fixture inventory. If the same file originally had def sample_payload() without @pytest.fixture, running the test would report it missing even though the function sits just above it. A typo in @pytest.fixture can instead cause an import or collection error, so read the first failure rather than looking only for the final summary.

Keep simple data factories as ordinary functions when they do not need pytest's lifecycle. In that case import and call the function explicitly from the test, without listing it as an injected parameter. Choose one contract: either pytest supplies a fixture by name or Python calls a helper. Mixing them obscures ownership of setup and teardown. For larger frameworks, building a Python API automation framework shows where reusable test setup belongs.

2. Fix pytest fixture not found across conftest.py directory boundaries

conftest.py applies to the directory containing it and descendants. A fixture in tests/api/conftest.py cannot flow sideways into tests/ui/test_nav.py. If both branches need the same fixture, place it in tests/conftest.py, their common ancestor. Use this layout for a self-contained example:

project/
  tests/
    conftest.py
    api/
      test_status.py
    ui/
      test_label.py

Create the three Python files as shown. sample_payload is shared without importing conftest in either test:

# tests/conftest.py
import pytest


@pytest.fixture
def sample_payload():
    return {"status": "ready"}
# tests/api/test_status.py
def test_status(sample_payload):
    assert sample_payload["status"] == "ready"
# tests/ui/test_label.py
def test_label(sample_payload):
    assert sample_payload["status"].upper() == "READY"

From project/, verify each branch independently and then together:

python -m pytest tests/api/test_status.py -q
python -m pytest tests/ui/test_label.py -q
python -m pytest tests -q

The final command should report two passing tests. If you move conftest.py back under tests/api/, the UI test should reproduce the lookup error. That controlled comparison is more useful than assuming an import path issue. Note that fixture scope, such as scope="session", controls how often an already visible fixture is created; it does not make a fixture in a child directory visible to a sibling. Keep shared fixtures at the narrowest common ancestor so unrelated suites do not silently depend on them.

3. Fix pytest fixture not found when conftest.py is not loaded

A correctly placed conftest.py can still be skipped by invocation settings. --noconftest disables loading conftest.py files. --confcutdir sets a boundary above which pytest does not search for them. An IDE may invoke a test path or working directory different from the one you use in a terminal. The pytest plugin loading order describes when initial conftest.py files are found.

Use the files from section 2. Ask pytest what it actually loaded, then run the test with the normal invocation:

python -m pytest --trace-config tests/ui/test_label.py -q
python -m pytest --fixtures tests/ui/test_label.py -q
python -m pytest tests/ui/test_label.py -q

Look for tests/conftest.py in the trace and sample_payload in the inventory. To reproduce the specific failure deliberately, compare with:

python -m pytest --noconftest tests/ui/test_label.py -q

The second invocation should fail with fixture 'sample_payload' not found; it is a diagnostic demonstration, not the final command to keep. Search your pytest configuration, IDE run configuration, and PYTEST_ADDOPTS for --noconftest or an inappropriate --confcutdir. Remove the setting at its source and rerun the normal command. Also confirm that a suite rooted under tests/ui/ has access to its intended ancestor. Do not assume pytest's displayed rootdir itself controls fixture visibility; it mainly reports configuration and collection context. The actual loaded conftest.py list is stronger evidence.

4. Fix pytest fixture not found from an unregistered helper module

An ordinary import tests.support.fixtures executes the module but does not automatically publish its decorated fixtures to the whole suite. Register a reusable module as a pytest plugin from a root conftest.py. This example uses package markers so the dotted module path is importable from the project root:

project/
  tests/
    __init__.py
    conftest.py
    support/
      __init__.py
      fixtures.py
    test_report.py

The two __init__.py files may be empty. Save these contents:

# tests/support/fixtures.py
import pytest


@pytest.fixture
def report_label():
    return "daily report"
# tests/conftest.py
pytest_plugins = ("tests.support.fixtures",)
# tests/test_report.py
def test_report_label(report_label):
    assert report_label.title() == "Daily Report"

Check the import, registered fixture, and test in that order:

python -c "import tests.support.fixtures; print('module import succeeds')"
python -m pytest --fixtures tests/test_report.py -q
python -m pytest tests/test_report.py -q

If the import command fails, fix the package layout or run from the intended project root before touching fixture registration. If import succeeds but report_label is absent, inspect whether the root conftest.py was loaded. The pytest plugin guide recommends declaring pytest_plugins in a root conftest.py; placing it in a nested conftest.py has restrictions and is deprecated for that use. For a small suite, defining the fixture directly in tests/conftest.py is simpler than creating a plugin module.

5. Fix pytest fixture not found for an optional plugin

A test that requests mocker needs the pytest-mock plugin. pytest itself does not supply that fixture. Install the package in the Python interpreter that runs the test; the pytest-mock documentation identifies mocker as its fixture. Put this test in tests/test_mocking.py:

# tests/test_mocking.py
import os


def test_home_lookup(mocker):
    mocker.patch("os.getcwd", return_value="/demo")
    assert os.getcwd() == "/demo"

Install and verify with one interpreter, not a bare pip paired with an unrelated pytest executable:

python -m pip install pytest pytest-mock
python -m pip show pytest-mock
python -m pytest --fixtures tests/test_mocking.py -q
python -m pytest tests/test_mocking.py -q

Expect mocker in the inventory and one passing test. If installation succeeds but the fixture is still absent, run python -m pytest --trace-config tests/test_mocking.py -q and look for the plugin. Check PYTEST_DISABLE_PLUGIN_AUTOLOAD, PYTEST_ADDOPTS, and any -p no:... option. Those can prevent an installed plugin from loading. Where autoload is intentionally disabled, explicitly load the plugin for this run and verify:

PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python -m pytest -p pytest_mock tests/test_mocking.py -q

Do not turn on every plugin to rescue one fixture. The same pattern applies to other plugin-owned names, including browser fixtures from pytest-playwright; first identify the package that owns the requested fixture, then confirm that package and plugin are present in the runner. If your browser suite uses that plugin, the Playwright Python CI guide covers its pipeline setup.

6. Fix pytest fixture not found when CI or Docker uses another interpreter

A laptop can have pytest-mock installed globally while a virtual environment, CI job, or container only has pytest. The test file is identical, but the plugin inventory is different. Capture interpreter and package evidence inside the failing environment. For CI, run this as a shell step before the test command:

python -c "import sys; print(sys.executable)"
python -m pip show pytest pytest-mock
python -m pytest --version
python -m pytest --trace-config tests/test_mocking.py -q
python -m pytest tests/test_mocking.py -q

If pip show cannot find pytest-mock, add it to the dependency file installed by that job, then rebuild the job environment. A local pip install does not update a lockfile or image. Verify the rebuilt environment with the same commands. python -m pytest uses the interpreter printed by sys.executable.

For Docker, create a minimal requirements.txt containing pytest and pytest-mock, plus the tests/test_mocking.py file from section 5. This Dockerfile runs that focused test without relying on packages on the host:

FROM python:<your-supported-python-version>-slim
WORKDIR /work
COPY requirements.txt .
RUN python -m pip install --no-cache-dir -r requirements.txt
COPY tests/ tests/
CMD ["python", "-m", "pytest", "tests/test_mocking.py", "-q"]

Replace the placeholder base-image tag with a Python version your project supports; do not paste the placeholder literally. Build and run the image after choosing it:

docker build -t pytest-fixture-check .
docker run --rm pytest-fixture-check

Expect one passing test. For multi-service integration suites, inspect the Docker Compose test environment guide. Changing a Compose service's network will not make a missing Python fixture appear; installation and plugin loading happen inside the test container. In CI, dependency caching must key off the dependency files, or a stale cache can keep the old environment; the GitHub Actions caching guide explains that trade-off.

7. Fix pytest fixture not found when a public fixture name differs

@pytest.fixture(name="user_record") registers a fixture under user_record even if the Python function is called make_user_record. A test parameter named make_user_record therefore requests the wrong fixture. This is easy to miss during a refactor that renames the function but not the decorator, or the decorator but not the tests.

Save this self-contained file as tests/test_user.py:

# tests/test_user.py
import pytest


@pytest.fixture(name="user_record")
def make_user_record():
    return {"id": 7, "active": True}


def test_active_user(user_record):
    assert user_record["active"] is True
    assert user_record["id"] == 7

Verify the public name and the test:

python -m pytest --fixtures tests/test_user.py -q
python -m pytest tests/test_user.py -q

The inventory should contain user_record, and the test should pass. If the test used make_user_record as its parameter, it would ask for a fixture that was never registered under that name. Choose a stable public name and use it consistently in test signatures, @pytest.mark.usefixtures("user_record"), and calls to request.getfixturevalue("user_record"). Avoid changing the Python function merely to silence the error if external tests depend on the public fixture name. When reviewing a failure, compare the exact quoted name to the fixture inventory character by character, including underscores.

8. Fix pytest fixture not found inside a dependency or indirect parameter

A fixture can request another fixture by naming it as a function argument. When the inner name is missing, the error can appear while pytest sets up the outer fixture. Define the dependency at a location visible to the test, or correct the inner spelling. This file has a complete dependency chain:

# tests/test_report_dependency.py
import pytest


@pytest.fixture
def sample_payload():
    return {"total": 3}


@pytest.fixture
def report(sample_payload):
    return f"Total: {sample_payload['total']}"


def test_report(report):
    assert report == "Total: 3"

Verify which fixtures a test uses and then execute it:

python -m pytest --fixtures-per-test tests/test_report_dependency.py -q
python -m pytest tests/test_report_dependency.py -q

If you delete sample_payload, pytest reports that missing dependency even though test_report requests only report. Do not rename report in response. Trace the chain from the missing name to the fixture signature that requests it.

Indirect parametrization creates another fixture request. In this separate file, pytest sends each parameter value to a fixture named region through request.param:

# tests/test_region.py
import pytest


@pytest.fixture
def region(request):
    return request.param.upper()


@pytest.mark.parametrize("region", ["us", "eu"], indirect=True)
def test_region_is_uppercase(region):
    assert region in {"US", "EU"}
python -m pytest --fixtures tests/test_region.py -q
python -m pytest tests/test_region.py -q

Expect two passing cases. If region is absent, the indirect parameter has nowhere to go. If you wanted ordinary values with no fixture transformation, remove indirect=True instead. This distinction is useful in data-driven test design and comes up in pytest interview questions.

How to Verify the Fix

Start with the exact node that failed. An inventory check tells you whether pytest can see the fixture, while an actual test run tells you whether setup and assertions work. In a project using tests/test_report_dependency.py from section 8, this sequence is concrete:

python -m pytest --fixtures tests/test_report_dependency.py -q
python -m pytest --fixtures-per-test tests/test_report_dependency.py -q
python -m pytest tests/test_report_dependency.py -q
python -m pytest tests -q

Expect sample_payload and report in the inventory, both in the selected test's fixture graph, one passing focused test, and a passing suite. The last command may legitimately include additional tests in your own project; review their results separately. For a plugin fixture, insert python -m pytest --trace-config ... and python -m pip show ... before the focused run. In a container, execute those commands inside the image, not merely on the host.

If --fixtures lists the name but the run fails, read the new error. Setup may now raise an exception, or another test directory may have different fixtures. Target that exact file. --collect-only proves collection, not setup. For flaky browser suites, do not mistake a later page failure for the original fixture error; keep the focused test and its first traceback in your diagnosis.

Prevent It From Coming Back

Keep fixture ownership obvious. Put fixtures used by only one module in that module, directory-wide fixtures in its conftest.py, and cross-suite fixtures in the nearest shared ancestor. Publish larger reusable fixture sets through a registered plugin module. Record optional plugin dependencies in the same dependency specification used by local, CI, and Docker runs.

Add a small focused test that requests critical shared fixtures and asserts a useful property, as test_report does above. Run that test in the pipeline before a long integration suite. The test catches both name loss and a setup failure after a refactor. If a fixture is expensive or reaches an external service, use a lightweight local contract test for its registration and a separate integration check for its real behavior.

Keep pytest invocation explicit in scripts: use python -m pytest from a known working directory and log the interpreter on CI failures. Review PYTEST_ADDOPTS and plugin autoload controls when changing runner images. Avoid importing conftest.py as an ordinary module, because its fixture discovery role is tied to pytest's directory loading. When reorganizing tests, run a fixture inventory for each moved branch, then execute the focused tests. A concise test automation CI/CD guide can help place those checks early in the pipeline.

Interview Questions and Answers

Q: What does fixture 'x' not found tell you?

pytest could not resolve x for the selected test during setup. I inspect the exact requested name and available fixtures, then locate where x is defined or which plugin provides it. I do not treat it as proof that the fixture's own code ran.

Q: Why does a sibling test module's fixture not work?

A test-module fixture is local to that module. I move shared setup to an appropriate conftest.py ancestor or register a plugin module, then verify from the sibling test path. Importing the module just for fixture registration is less clear.

Q: What do --fixtures and --fixtures-per-test show?

--fixtures lists names available to the selected test context. --fixtures-per-test shows which fixtures each selected test uses, including dependencies. I run the actual test afterward because neither listing proves setup succeeds.

Q: How can a session-scoped fixture still be unavailable?

scope="session" controls lifetime after resolution. A fixture in a nested conftest.py remains invisible to tests outside that directory tree. I change its definition location, not its lifetime, when visibility is the issue.

Q: How do you diagnose a missing mocker fixture in CI?

I check whether pytest-mock is installed in the exact interpreter running pytest and whether the plugin loaded. I inspect PYTEST_DISABLE_PLUGIN_AUTOLOAD and -p no:... if installation is present. A focused mocking test proves the repair.

Q: Why can the error name a fixture the test does not mention?

Fixtures request other fixtures through their parameters, and indirect parametrization also requests a named fixture. I follow the setup chain to the first unresolved name. Renaming the outer test parameter would miss the cause.

Common Mistakes

  • Adding scope="session" to a fixture that is outside the test's directory visibility. Lifetime does not change lookup boundaries.
  • Installing a plugin with one interpreter and launching pytest from another. Pair python -m pip with python -m pytest.
  • Importing conftest.py directly. Let pytest load it by directory, or move reusable fixtures to a registered plugin module.
  • Fixing the requested name without checking a nested fixture dependency. Read the quoted missing name in the current traceback.
  • Running --fixtures against a different test directory. Visibility is tied to the selected test, so target the failing file.
  • Assuming --collect-only proves fixture setup. Collection can succeed while fixture resolution fails when the test starts.
  • Copying a Docker base image placeholder into a real build. Choose a supported installed Python version for your project.
  • Hiding plugin registration failures by globally enabling every plugin. Load only the dependency that owns the missing fixture.

Conclusion

To resolve the pytest "fixture not found" error, identify the exact missing name, inspect the fixture inventory for the failing test, and repair the registration, visibility, plugin, or interpreter that owns it. Run the focused test after the inventory check, then rerun the affected suite in the same local, CI, or Docker environment that originally failed. That sequence proves both name resolution and working setup.

Interview Questions and Answers

How would you investigate pytest fixture not found in a large suite?

I capture the missing name and the exact test node, then list fixtures for that test file. I compare the registered fixture name with the test signature and check applicable conftest.py files. If a plugin owns the fixture, I inspect the active interpreter and plugin trace before running the focused test.

What is the difference between fixture visibility and fixture scope?

Visibility determines whether a test can resolve a fixture at all. Scope determines how long pytest caches a fixture instance once it is resolved. A session-scoped fixture in a child conftest.py still cannot serve an unrelated sibling directory.

When should a fixture move into conftest.py?

I move it when multiple test modules in the same directory tree need the same setup. I place it at their narrowest common ancestor so unrelated tests do not acquire that fixture. For broader reuse, I consider a registered plugin module.

How would you distinguish a missing fixture from a setup failure?

A missing fixture reports `fixture 'name' not found` and lists available names. A setup failure shows an exception raised by code inside a fixture that pytest already resolved. I use the first traceback and a focused rerun to identify which stage failed.

What would you check when mocker works locally but fails in Docker?

I run `python -m pip show pytest-mock` and `python -m pytest --trace-config` inside the image. Then I check that the image installs the dependency file containing pytest-mock and is rebuilt. Host packages do not supply fixtures to the container.

Why can a fixture error name a dependency absent from the test signature?

The test can request an outer fixture whose function arguments request more fixtures. pytest resolves the whole dependency graph before executing the test. I find the fixture function that names the unresolved dependency and repair that edge.

What is the purpose of pytest_plugins in a root conftest.py?

It registers an importable module as a pytest plugin, which can publish fixtures to the suite. I verify the dotted module imports and that pytest loads the root conftest.py. For a few simple fixtures, direct definitions in conftest.py may be easier to maintain.

Frequently Asked Questions

Why does pytest say fixture not found when the function exists?

A Python function is not automatically a fixture. Add `@pytest.fixture` and request the registered name, or call the function as an ordinary helper. If it is in another module, make sure pytest loads that module as a plugin or from an applicable conftest.py.

Where should I put conftest.py for shared fixtures?

Place it in the nearest directory that is an ancestor of every test that needs those fixtures. A conftest.py under one sibling directory cannot supply fixtures to another sibling. Verify each branch with `python -m pytest --fixtures <test-file>`.

Does fixture scope make a fixture available everywhere?

No. Scope controls how long an already resolved fixture instance lives. Visibility comes from the test module, its applicable conftest.py ancestors, and loaded plugins.

Why is the mocker fixture missing in pytest?

The `mocker` fixture is supplied by pytest-mock, not pytest core. Install pytest-mock in the interpreter used for `python -m pytest`, then check `--trace-config` if plugin autoload is disabled. Run a focused test to confirm setup works.

Why does the fixture error happen only in CI?

CI may use another interpreter, dependency set, plugin-loading policy, or test path. Print `sys.executable`, inspect installed packages, and run `--trace-config` in the job. Rebuild the environment after changing its dependency specification.

How do I list fixtures for one pytest test file?

Run `python -m pytest --fixtures path/to/test_file.py -q`. Use `--fixtures-per-test` to inspect the requested fixture graph. Repeat against the exact failing file because directory visibility differs.

Can indirect parametrization cause fixture not found?

Yes. With `@pytest.mark.parametrize(..., indirect=True)`, pytest looks for a fixture with the parameter's name. Define that fixture and read `request.param`, or remove `indirect=True` if direct values were intended.

Related Guides