pytest ScopeMismatch with tmp_path: two small repairs

pytest ScopeMismatch with tmp_path: two small repairs

GlebNatureStudio

A session-scoped fixture that requests tmp_path can stop a test during setup with ScopeMismatch. Choose how long the directory should live, then match the fixture dependency to that lifetime. Here is a complete, small exercise with two working repairs.

1. Reproduce the setup error

Save this as broken_demo.py in a separate folder with pytest available in your selected Python environment:

"""Run explicitly with pytest. This example is intended to error in setup."""
import pytest


@pytest.fixture(scope="session")
def report_root(tmp_path):
    return tmp_path


def test_report_root_exists(report_root):
    assert report_root.is_dir()

Run in your shell, separately from the Python file: python -m pytest -q broken_demo.py

Expected: one setup error containing ScopeMismatch. The assertion in the test body is not reached. The report_root fixture lives for the session, while tmp_path supplies a directory for an individual test invocation.

2. Choose an isolated directory for each test

For tests that create and change their own files, use a function-scoped fixture. The default scope already provides that lifetime. Save this complete replacement as per_test_demo.py:

"""Each parameterized test receives its own empty working directory."""
import pytest


@pytest.fixture
def report_root(tmp_path):
    return tmp_path


@pytest.mark.parametrize("filename", ["summary.txt", "detail.txt"])
def test_clean_workspace(report_root, filename):
    assert list(report_root.iterdir()) == []
    output = report_root / filename
    output.write_text("ready\n", encoding="utf-8")
    assert output.read_text(encoding="utf-8") == "ready\n"

Run in your shell, separately from the Python file: python -m pytest -q per_test_demo.py

Expected: two tests pass. The empty-directory assertion runs once for each parameter value. Each invocation gets a fresh directory, writes its report, then reads the actual contents back.

3. Choose an intentionally shared session directory

When the suite deliberately needs one directory for a session, request tmp_path_factory. Save this alternative as session_demo.py:

"""One intentionally shared session directory, with separate output names."""
import pytest


@pytest.fixture(scope="session")
def report_root(tmp_path_factory):
    return tmp_path_factory.mktemp("reports")


@pytest.mark.parametrize("filename", ["summary.txt", "detail.txt"])
def test_separate_reports(report_root, filename):
    output = report_root / filename
    assert not output.exists()
    output.write_text("ready\n", encoding="utf-8")
    assert output.read_text(encoding="utf-8") == "ready\n"

Run in your shell, separately from the Python file: python -m pytest -q session_demo.py

Expected: two tests pass. Both tests use the same session root and write different filenames. Files in that root persist across tests in that Python process. Keep cached inputs read-only or give each test a distinct output name when shared storage is intentional.

A quick diagnostic order

  1. Identify the failing phase. ScopeMismatch here occurs while preparing fixtures, before the test body.
  2. Read the fixture chain in the error. Find the longer-lived fixture that requests the shorter-lived dependency.
  3. Choose the required lifetime: fresh files per test, or deliberately shared session data.
  4. Run the repaired file explicitly. Confirm both the exit status and the file-content assertions.
  5. Return to the original suite after the small reproduction behaves as expected. Check its plugins and other fixture dependencies separately.

Verification and references

These three original example files were run separately with CPython 3.9.6 and pytest 8.4.2, with third-party plugin autoload disabled. The broken file produced one ScopeMismatch setup error; each repaired file passed two tests. The demonstration uses one Python process per run.

For a clean reproduction in a shell that supports this prefix, run PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python -m pytest -q FILE.py. Use the corresponding environment-variable syntax for your shell.

More worked repair cases

pytest Failure Diagnosis Lab is a related paid EPUB with 24 original broken-and-repaired cases covering fixtures, parametrization, exceptions, temporary paths, mocking and other diagnostic topics. Its public listing was US $7.99 when checked; the product page and checkout show the current price and any applicable tax.

This free standalone exercise and article were created with material AI assistance using OpenAI Codex. You may copy and adapt these small synthetic examples. The related ebook is also labeled AI-assisted on its product page.

Report Page