Skip to content

Commit 8606fdc

Browse files
committed
testing: add some more tests for fixture closure
Explicitly test a couple more scenarios. One of the tests doesn't currently pass so marked xfail.
1 parent d036b12 commit 8606fdc

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

testing/python/fixtures.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5198,3 +5198,110 @@ def test_something(self, request, app):
51985198
)
51995199
result = pytester.runpytest("-v")
52005200
result.assert_outcomes(passed=1)
5201+
5202+
5203+
def test_fixture_closure_handles_circular_dependencies(pytester: Pytester) -> None:
5204+
"""Test that getfixtureclosure properly handles circular dependencies.
5205+
5206+
The test will error in the runtest phase due to the fixture loop,
5207+
but the closure computation still completes.
5208+
"""
5209+
pytester.makepyfile(
5210+
"""
5211+
import pytest
5212+
5213+
# Direct circular dependency.
5214+
@pytest.fixture
5215+
def fix_a(fix_b): pass
5216+
5217+
@pytest.fixture
5218+
def fix_b(fix_a): pass
5219+
5220+
# Indirect circular dependency through multiple fixtures.
5221+
@pytest.fixture
5222+
def fix_x(fix_y): pass
5223+
5224+
@pytest.fixture
5225+
def fix_y(fix_z): pass
5226+
5227+
@pytest.fixture
5228+
def fix_z(fix_x): pass
5229+
5230+
def test_circular_deps(fix_a, fix_x):
5231+
pass
5232+
"""
5233+
)
5234+
items, _hookrec = pytester.inline_genitems()
5235+
assert isinstance(items[0], Function)
5236+
assert items[0].fixturenames == ["fix_a", "fix_x", "fix_b", "fix_y", "fix_z"]
5237+
5238+
5239+
def test_fixture_closure_handles_diamond_dependencies(pytester: Pytester) -> None:
5240+
"""Test that getfixtureclosure properly handles diamond dependencies."""
5241+
pytester.makepyfile(
5242+
"""
5243+
import pytest
5244+
5245+
@pytest.fixture
5246+
def db(): pass
5247+
5248+
@pytest.fixture
5249+
def user(db): pass
5250+
5251+
@pytest.fixture
5252+
def session(db): pass
5253+
5254+
@pytest.fixture
5255+
def app(user, session): pass
5256+
5257+
def test_diamond_deps(request, app):
5258+
assert request.node.fixturenames == ["request", "app", "user", "session", "db"]
5259+
assert request.fixturenames == ["request", "app", "user", "session", "db"]
5260+
"""
5261+
)
5262+
result = pytester.runpytest("-v")
5263+
result.assert_outcomes(passed=1)
5264+
5265+
5266+
@pytest.mark.xfail(reason="not currently handled correctly")
5267+
def test_fixture_closure_with_complex_override_and_shared_deps(
5268+
pytester: Pytester,
5269+
) -> None:
5270+
"""Test that shared dependencies in override chains are processed only once."""
5271+
pytester.makeconftest(
5272+
"""
5273+
import pytest
5274+
5275+
@pytest.fixture
5276+
def db(): pass
5277+
5278+
@pytest.fixture
5279+
def cache(): pass
5280+
5281+
@pytest.fixture
5282+
def settings(): pass
5283+
5284+
@pytest.fixture
5285+
def app(db, cache, settings): pass
5286+
"""
5287+
)
5288+
pytester.makepyfile(
5289+
"""
5290+
import pytest
5291+
5292+
# Override app, but also directly use cache and settings.
5293+
# This creates multiple paths to the same fixtures.
5294+
@pytest.fixture
5295+
def app(app, cache, settings): pass
5296+
5297+
class TestClass:
5298+
# Another override that uses both app and cache.
5299+
@pytest.fixture
5300+
def app(self, app, cache): pass
5301+
5302+
def test_shared_deps(self, request, app):
5303+
assert request.node.fixturenames == ["request", "app", "db", "cache", "settings"]
5304+
"""
5305+
)
5306+
result = pytester.runpytest("-v")
5307+
result.assert_outcomes(passed=1)

0 commit comments

Comments
 (0)