Skip to content

Conftest fixtures leak to sibling directories when testpaths points outside rootdir #14004

@akwasigroch

Description

@akwasigroch

Bug Description

When testpaths in pyproject.toml points to a directory outside the rootdir using a relative path like ../tests/sdk, conftest.py fixture scoping does not work correctly. Fixtures from nested conftest.py files leak to sibling directories instead of being scoped to their subdirectory.

Directory Structure

.
├── sdk/
│   └── pyproject.toml
└── tests/
    └── sdk/
        ├── conftest.py
        ├── test_outer.py
        └── inner/
            ├── conftest.py
            └── test_inner.py

Expected Behavior

Fixtures defined in tests/sdk/inner/conftest.py should only apply to tests in the inner/ subdirectory, not to sibling test files like test_outer.py.

Actual Behavior

When using testpaths = ["../tests/sdk"] from sdk/pyproject.toml:

  • Fixtures from tests/sdk/inner/conftest.py are incorrectly applied to ALL tests, including test_outer.py
  • This does NOT happen when running pytest with an explicit path instead of relying on testpaths

Reproduction Files

sdk/pyproject.toml:

[project]
name = "sdk"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
    "pytest>=9.0.1",
]
[tool.pytest.ini_options]
testpaths = ["../tests/sdk"]

tests/sdk/conftest.py:

import pytest


@pytest.fixture(autouse=True)
def outer_fixture():
    print("outer_fixture")

tests/sdk/inner/conftest.py:

import pytest


@pytest.fixture(autouse=True)
def inner_fixture():
    print("inner_fixture")

tests/sdk/test_outer.py:

def test_outer():
    assert 1 == 1
def test_outer_2():
    assert 1 == 1
def test_outer_3():
    assert 1 == 1
def test_outer_4():
    assert 1 == 1
def test_outer_5():
    assert 1 == 1
def test_outer_6():
    assert 1 == 1
def test_outer_7():
    assert 1 == 1
def test_outer_8():
    assert 1 == 1

tests/sdk/inner/test_inner.py:

def test_inner():
    assert 1 == 1

Steps to Reproduce

  1. Create the directory structure and files as shown above
  2. Run from the sdk/ directory:

Case 1: Using testpaths (BROKEN)

cd sdk
pytest -s

Output:

============================= test session starts ==============================
platform darwin -- Python 3.10.17, pytest-9.0.1, pluggy-1.6.0
rootdir: /Users/arek/Desktop/untitled folder/sdk
configfile: pyproject.toml
testpaths: ../tests/sdk
collected 9 items

inner/test_inner.py outer_fixture
inner_fixture
.
test_outer.py outer_fixture
inner_fixture    <-- BUG: inner_fixture should NOT be applied here!
.outer_fixture
inner_fixture    <-- BUG: inner_fixture should NOT be applied here!
.outer_fixture
inner_fixture    <-- BUG: inner_fixture should NOT be applied here!
.outer_fixture
inner_fixture    <-- BUG: inner_fixture should NOT be applied here!
.outer_fixture
inner_fixture    <-- BUG: inner_fixture should NOT be applied here!
.outer_fixture
inner_fixture    <-- BUG: inner_fixture should NOT be applied here!
.outer_fixture
inner_fixture    <-- BUG: inner_fixture should NOT be applied here!
.outer_fixture
inner_fixture    <-- BUG: inner_fixture should NOT be applied here!
.

============================== 9 passed in 0.00s ===============================

Case 2: Using explicit path (CORRECT)

cd sdk
pytest -s ../tests/sdk

Output:

============================= test session starts ==============================
platform darwin -- Python 3.10.17, pytest-9.0.1, pluggy-1.6.0
rootdir: /Users/arek/Desktop/untitled folder
collected 9 items

../tests/sdk/inner/test_inner.py outer_fixture
inner_fixture
.
../tests/sdk/test_outer.py outer_fixture    <-- CORRECT: only outer_fixture
.outer_fixture                              <-- CORRECT: only outer_fixture
.outer_fixture                              <-- CORRECT: only outer_fixture
.outer_fixture                              <-- CORRECT: only outer_fixture
.outer_fixture                              <-- CORRECT: only outer_fixture
.outer_fixture                              <-- CORRECT: only outer_fixture
.outer_fixture                              <-- CORRECT: only outer_fixture
.outer_fixture                              <-- CORRECT: only outer_fixture
.

============================== 9 passed in 0.00s ===============================

Environment

  • pytest version: 9.0.1
  • Python version: 3.10.17
  • Platform: macOS (darwin), Ubuntu 24.04 (WSL)

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: collectionrelated to the collection phasetopic: fixturesanything involving fixtures directly or indirectly

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions