diff --git a/AUTHORS b/AUTHORS index e670571566a..e5c19cdca0d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -43,6 +43,7 @@ Anthony Shaw Anthony Sottile Anton Grinevich Anton Lodder +Anton Zhilin Antony Lee Arel Cordero Arias Emmanuel diff --git a/changelog/13248.bugfix.rst b/changelog/13248.bugfix.rst new file mode 100644 index 00000000000..2ebb102fd07 --- /dev/null +++ b/changelog/13248.bugfix.rst @@ -0,0 +1,2 @@ +Fixed an issue where passing a ``scope`` in :py:func:`Metafunc.parametrize ` with ``indirect=True`` +could result in other fixtures being unable to depend on the parametrized fixture. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index dcd06c3b40a..bb50b014dd1 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -605,7 +605,12 @@ def _get_active_fixturedef( param_index = 0 scope = fixturedef._scope self._check_fixturedef_without_param(fixturedef) - self._check_scope(fixturedef, scope) + # The parametrize invocation scope only controls caching behavior while + # allowing wider-scoped fixtures to keep depending on the parametrized + # fixture. Scope control is enforced for parametrized fixtures + # by recreating the whole fixture tree on parameter change. + # Hence `fixturedef._scope`, not `scope`. + self._check_scope(fixturedef, fixturedef._scope) subrequest = SubRequest( self, scope, param, param_index, fixturedef, _ispytest=True ) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index dc69781095b..c8d1eb23838 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -5009,3 +5009,31 @@ def test_result(): ) result = pytester.runpytest() assert result.ret == 0 + + +def test_parametrized_fixture_scope_allowed(pytester: Pytester) -> None: + """ + Make sure scope from parametrize does not affect fixture's ability to be + depended upon. + + Regression test for #13248 + """ + pytester.makepyfile( + """ + import pytest + + @pytest.fixture(scope="session") + def my_fixture(request): + return getattr(request, "param", None) + + @pytest.fixture(scope="session") + def another_fixture(my_fixture): + return my_fixture + + @pytest.mark.parametrize("my_fixture", ["a value"], indirect=True, scope="function") + def test_foo(another_fixture): + assert another_fixture == "a value" + """ + ) + result = pytester.runpytest() + result.assert_outcomes(passed=1)