Skip to content

Fix: pytest fixture Not Found – ERRORS or 'fixture not found' in Test Collection

FixDevs ·

Quick Answer

How to fix pytest errors like 'fixture not found', 'ERRORS collecting test', or 'no tests ran' caused by missing conftest.py, wrong scope, or import issues.

The Error

You run your test suite with pytest and instead of green passes, you get something like this:

ERRORS collecting tests/test_api.py
E       fixture 'db_session' not found
>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, ...

Or this variation during collection:

collected 0 items / 1 error

============================== ERRORS ==============================
________________ ERROR collecting tests/test_api.py ________________
tests/test_api.py::test_create_user
  E       fixture 'db_session' not found
>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, ...
========================= no tests ran ==========================

You might also see it phrased differently depending on your pytest version:

E       fixture 'app_client' not found
>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, ...
>       use 'pytest --fixtures [testpath]' for help on them.

The message is clear: pytest is looking for a fixture you referenced in a test function’s parameter list, but it cannot find it. The fixture either does not exist, is defined in the wrong place, or is invisible to the test file that needs it.

Why This Happens

pytest’s fixture system works through dependency injection. When you write a test function like def test_something(db_session):, pytest looks for a fixture named db_session and injects it automatically. It searches for fixtures in a specific order:

  1. The test file itself. Fixtures defined with @pytest.fixture in the same file as the test.
  2. conftest.py files. Starting from the directory containing the test file and walking up to the rootdir. Each conftest.py along the path is checked.
  3. Plugins. Fixtures provided by installed pytest plugins (like pytest-django, pytest-asyncio, etc.).
  4. Built-in fixtures. pytest’s own fixtures like tmp_path, capsys, monkeypatch, etc.

If the fixture name does not match anything in this search path, pytest raises the “fixture not found” error. The most common reasons:

  • The fixture is defined in a file that is not a conftest.py and not the test file itself. pytest does not auto-discover fixtures from arbitrary Python files.
  • The conftest.py is in the wrong directory. It must be at or above the test file in the directory hierarchy.
  • A typo in the fixture name or a parametrize decorator.
  • Missing __init__.py files causing pytest to misidentify the package structure.
  • The fixture scope is wrong or ordering conflicts prevent proper resolution.
  • Configuration issues in pytest.ini, pyproject.toml, or setup.cfg that change the rootdir or test paths.

Fix 1: Create or Move Your conftest.py

This is the number one cause. You defined a fixture in some utility file or a random module, but pytest only auto-discovers fixtures in conftest.py files and in the test files themselves.

Broken structure:

project/
├── tests/
│   ├── test_api.py          # uses db_session fixture
│   └── fixtures.py          # db_session is defined here -- pytest won't find it

Fixed structure:

project/
├── tests/
│   ├── conftest.py          # db_session is defined here -- pytest finds it
│   └── test_api.py          # uses db_session fixture

Move your fixture into conftest.py:

# tests/conftest.py
import pytest

@pytest.fixture
def db_session():
    session = create_test_session()
    yield session
    session.rollback()
    session.close()
# tests/test_api.py
def test_create_user(db_session):
    user = db_session.add(User(name="Alice"))
    assert user.name == "Alice"

You do not import the fixture. That is the key thing people miss. pytest finds conftest.py automatically and makes its fixtures available to all tests in the same directory and subdirectories. If you are importing fixtures manually, you are doing it wrong.

conftest.py hierarchy

You can have multiple conftest.py files at different levels. Fixtures in a parent directory’s conftest.py are available to all subdirectories:

project/
├── tests/
│   ├── conftest.py           # fixtures available to ALL tests
│   ├── unit/
│   │   ├── conftest.py       # fixtures available only to unit tests
│   │   └── test_models.py
│   └── integration/
│       ├── conftest.py       # fixtures available only to integration tests
│       └── test_api.py

A fixture in tests/conftest.py is visible to both tests/unit/ and tests/integration/. A fixture in tests/unit/conftest.py is only visible to tests inside tests/unit/.

Fix 2: Fix Fixture Name Typos and parametrize Mistakes

A surprisingly common cause is a simple typo. The fixture is defined correctly, but the test function parameter has a slightly different name.

# conftest.py
@pytest.fixture
def api_client():
    return TestClient(app)
# test_api.py
def test_endpoint(api_cient):  # typo: "cient" instead of "client"
    response = api_cient.get("/health")
    assert response.status_code == 200

pytest will report fixture 'api_cient' not found. Check your spelling carefully.

parametrize typos

Another frequent source of this error is misspelling parametrize (one “e”, not “parameterize”) or mismatching the parameter names:

# Wrong: "parameterize" has an extra 'e' -- this is silently treated as
# an unknown marker, not a parametrize call
@pytest.mark.parameterize("input,expected", [(1, 2), (3, 4)])
def test_double(input, expected):
    assert input * 2 == expected
# Correct: "parametrize" (no second 'e')
@pytest.mark.parametrize("input_val,expected", [(1, 2), (3, 4)])
def test_double(input_val, expected):
    assert input_val * 2 == expected

Also make sure the string argument names in @pytest.mark.parametrize match the function parameter names exactly:

# Broken: parametrize says "value" but function says "val"
@pytest.mark.parametrize("value", [1, 2, 3])
def test_thing(val):  # fixture 'val' not found
    assert val > 0

Pro Tip: Run pytest --fixtures to see every fixture pytest can discover, along with where each one is defined. If your fixture does not appear in this list, pytest cannot find it. This is the fastest way to debug fixture visibility issues. You can also scope it to a specific test path: pytest --fixtures tests/unit/ to see what is available in that directory.

Fix 3: Add Missing init.py Files

pytest uses __init__.py files to understand your project’s package structure. Missing __init__.py files can cause pytest to treat directories as separate root directories, which breaks conftest.py discovery.

project/
├── tests/
│   ├── __init__.py           # add this
│   ├── conftest.py
│   ├── unit/
│   │   ├── __init__.py       # add this
│   │   └── test_models.py
│   └── integration/
│       ├── __init__.py       # add this
│       └── test_api.py

Without __init__.py files, pytest might not walk up the directory tree correctly to find conftest.py files in parent directories. This is especially common when you have tests in nested subdirectories.

If your project uses src layout, make sure the __init__.py files exist in the test directories even if your source code uses namespace packages (implicit namespace packages without __init__.py).

Note that this is related to a broader Python packaging issue. If you are also seeing import errors in your regular code, see Fix: ModuleNotFoundError: No module named in Python for a deeper dive into how Python resolves modules.

Fix 4: Check pytest Configuration (pytest.ini / pyproject.toml)

Your pytest configuration might be setting rootdir or testpaths in a way that excludes the directory where your conftest.py lives.

Check your configuration files:

pyproject.toml:

[tool.pytest.ini_options]
testpaths = ["tests"]

pytest.ini:

[pytest]
testpaths = tests

setup.cfg:

[tool:pytest]
testpaths = tests

If testpaths is set to tests but your conftest.py is in the project root, pytest will not discover it. Either move the conftest.py into the tests/ directory or add the project root to the test paths.

Also check for rootdir misdetection. When you run pytest, it prints the rootdir at the start:

========================= test session starts =========================
platform linux -- Python 3.12.0, pytest-8.0.0
rootdir: /home/user/project
configfile: pyproject.toml

If rootdir is not what you expect, pytest might be looking in the wrong place for conftest.py files. The rootdir is determined by the location of your config file (pytest.ini, pyproject.toml, or setup.cfg) combined with the paths you pass on the command line.

If you are also dealing with environment variables in your test configuration, check out Fix: Environment Variable is Undefined or Empty for common pitfalls.

Fix 5: Fix Fixture Scope Issues

Fixtures have scopes that control their lifetime: function (default), class, module, package, and session. A fixture with a narrower scope cannot use a fixture with a broader scope in certain configurations, and vice versa depending on how they are composed.

@pytest.fixture(scope="session")
def database():
    db = create_database()
    yield db
    db.drop()

@pytest.fixture(scope="function")
def db_session(database):
    session = database.create_session()
    yield session
    session.rollback()

This works fine. A function-scoped fixture can depend on a session-scoped fixture. But the reverse does not work:

@pytest.fixture(scope="session")
def expensive_resource(db_session):  # ERROR: session-scoped can't use function-scoped
    ...

pytest will raise a ScopeMismatch error (which can sometimes manifest as fixture-not-found in older versions). The rule is: a fixture can only depend on fixtures with equal or broader scope.

Scope hierarchy from broadest to narrowest: session > package > module > class > function

If you need a session-scoped fixture to set up something that depends on a database, make the database fixture session-scoped too:

@pytest.fixture(scope="session")
def database():
    db = create_database()
    yield db
    db.drop()

@pytest.fixture(scope="session")
def expensive_resource(database):
    return database.load_resource()

Fix 6: Understand Fixture Ordering and autouse

autouse fixtures

Fixtures with autouse=True are automatically applied to every test in their scope without being listed as a parameter. They are useful for setup/teardown that should always run:

@pytest.fixture(autouse=True)
def reset_environment():
    os.environ["TEST_MODE"] = "true"
    yield
    del os.environ["TEST_MODE"]

If you expect a fixture to run automatically but it does not have autouse=True, it will not run unless a test explicitly requests it by name. This is not a “fixture not found” error, but it is a common source of confusion when tests pass without the expected setup.

Conversely, if you have an autouse fixture in a conftest.py that depends on another fixture and that dependency cannot be found, every test in scope will fail with “fixture not found.”

Fixture ordering

When a test depends on multiple fixtures, pytest resolves them based on dependencies and scope. If fixture A depends on fixture B, B is set up first. If there is no dependency between them, the order follows the parameter list. This usually does not cause “fixture not found” errors, but it can cause confusing failures if the order matters for your setup logic.

def test_something(clean_db, populated_db):
    # clean_db runs first, then populated_db
    # If populated_db depends on clean_db, declare it explicitly:
    pass

@pytest.fixture
def populated_db(clean_db):  # explicit dependency ensures correct order
    clean_db.insert(test_data)
    return clean_db

Fix 7: Use Factory Fixtures for Dynamic Setup

Sometimes the “fixture not found” error appears because you are trying to pass arguments to a fixture, which is not how pytest fixtures work. Instead, use the factory pattern:

This does not work:

@pytest.fixture
def user(name, role):  # "name" and "role" are treated as fixture names
    return User(name=name, role=role)

def test_admin(user):
    # How do you pass name="admin" and role="admin"?
    pass

pytest will try to find fixtures named name and role, which do not exist. Use a factory fixture instead:

@pytest.fixture
def make_user(db_session):
    def _make_user(name="default", role="viewer"):
        user = User(name=name, role=role)
        db_session.add(user)
        db_session.commit()
        return user
    return _make_user

def test_admin(make_user):
    admin = make_user(name="admin", role="admin")
    assert admin.role == "admin"

def test_viewer(make_user):
    viewer = make_user(name="viewer")
    assert viewer.role == "viewer"

The fixture returns a callable (a factory function) instead of an object. Each test can call the factory with different arguments. This pattern avoids the “fixture not found” error and gives you flexibility.

Common Mistake: Defining fixtures inside test classes without the self parameter or without using @staticmethod. If your fixture is a method inside a test class, it needs self as the first parameter just like any other method, or pytest will try to resolve self as a fixture and fail. In general, prefer defining fixtures in conftest.py rather than inside test classes.

Fix 8: Plugin and Third-Party Fixture Issues

Some pytest plugins provide fixtures that are only available when the plugin is installed and properly configured.

pytest-django provides fixtures like db, client, rf, and admin_client. If you see:

E       fixture 'db' not found

Make sure pytest-django is installed and your DJANGO_SETTINGS_MODULE is set:

pip install pytest-django
# pyproject.toml
[tool.pytest.ini_options]
DJANGO_SETTINGS_MODULE = "myproject.settings"

pytest-asyncio provides event_loop and the @pytest.mark.asyncio marker. If async test fixtures are not found, install the plugin:

pip install pytest-asyncio

If you are having trouble installing these packages, see Fix: No Matching Distribution Found for pip install for troubleshooting pip install failures.

Check what plugins are active:

pytest --co -q

Or list all installed plugins:

pip list | grep pytest

If a plugin fixture name collides with your own fixture, your local fixture takes precedence. But if you accidentally shadow a built-in fixture without realizing it, tests that depend on the original behavior will break.

Fix 9: Fixture Import Pitfalls

While you should not import fixtures from arbitrary modules, there is one legitimate way to share fixtures across projects or between files outside the conftest hierarchy: pytest_plugins.

In a conftest.py file, you can declare:

# conftest.py
pytest_plugins = ["myproject.testing.fixtures", "myproject.testing.database"]

This tells pytest to load fixtures from those modules as if they were defined in a conftest.py. The modules must be importable (on sys.path).

However, this has a catch: pytest_plugins must be defined at the top level of a conftest.py and should not be used in non-root conftest.py files (pytest will warn about this in newer versions). If you are seeing import errors related to the modules listed in pytest_plugins, ensure they are on the Python path and do not have circular import issues.

Another common import pitfall: if your test files or conftest files have import-time errors (such as importing a module that does not exist), pytest will report a collection error that can look similar to a fixture-not-found error. Check the full traceback carefully. If you see ModuleNotFoundError in the traceback, the problem is an import failure, not a missing fixture. Fix the import first.

If you keep hitting Python import errors when setting up your test environment, make sure Python is correctly installed and on your PATH.

Still Not Working?

Run verbose fixture discovery

pytest --fixtures -v

This lists every available fixture, its scope, and the file where it is defined. Search for your fixture name in the output. If it is not there, pytest genuinely cannot see it.

Check collection with verbose output

pytest --collect-only -q

This shows which tests pytest finds without running them. If your test file does not appear in the list, pytest is not collecting it. Common reasons: the file is not named test_*.py or *_test.py, or the directory is excluded by your config.

If you suspect path issues, add this to your conftest.py:

import sys
print("sys.path:", sys.path)

Then run pytest -s to see the output. This helps you verify that your project root is on the path and that modules can be imported.

Recreate your virtual environment

If fixtures were working before and suddenly stopped, your environment might be corrupted. Rebuild it:

rm -rf .venv
python -m venv .venv
source .venv/bin/activate   # or .venv\Scripts\activate on Windows
pip install -e ".[test]"    # or pip install -r requirements-test.txt
pytest --fixtures            # verify fixtures are visible

Use pytest-randomly or change test order

In rare cases, fixture-not-found errors only appear when tests run in a specific order. This can happen when one test file’s conftest.py defines a fixture that another test file accidentally depends on via some shared state. Running tests in random order helps surface these hidden dependencies:

pip install pytest-randomly
pytest -p randomly

Related: If pip cannot find or install the testing packages you need, see Fix: No Matching Distribution Found for pip install.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles