diff --git a/changelog/11234.bugfix.rst b/changelog/11234.bugfix.rst new file mode 100644 index 000000000..54dfafad2 --- /dev/null +++ b/changelog/11234.bugfix.rst @@ -0,0 +1 @@ +Fixed the case that when there are multiple fixturedefs for a param, _find_parametrized_scope picks the farthest one, while it should pick the nearest one. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 00c2a8ef4..6e99ec188 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -492,7 +492,7 @@ class FixtureRequest: node: Optional[Union[nodes.Item, nodes.Collector]] = self._pyfuncitem elif scope is Scope.Package: # FIXME: _fixturedef is not defined on FixtureRequest (this class), - # but on FixtureRequest (a subclass). + # but on SubRequest (a subclass). node = get_scope_package(self._pyfuncitem, self._fixturedef) # type: ignore[attr-defined] else: node = get_scope_node(self._pyfuncitem, scope) diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 98c61d4fc..6a2d79bf0 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1505,6 +1505,66 @@ class TestMetafuncFunctional: result = pytester.runpytest() assert result.ret == 0 + def test_reordering_with_scopeless_and_just_indirect_parametrization( + self, pytester: Pytester + ) -> None: + pytester.makeconftest( + """ + import pytest + + @pytest.fixture(scope="package") + def fixture1(): + pass + """ + ) + pytester.makepyfile( + """ + import pytest + + @pytest.fixture(scope="module") + def fixture0(): + pass + + @pytest.fixture(scope="module") + def fixture1(fixture0): + pass + + @pytest.mark.parametrize("fixture1", [0], indirect=True) + def test_0(fixture1): + pass + + @pytest.fixture(scope="module") + def fixture(): + pass + + @pytest.mark.parametrize("fixture", [0], indirect=True) + def test_1(fixture): + pass + + def test_2(): + pass + + class Test: + @pytest.fixture(scope="class") + def fixture(self): + pass + + @pytest.mark.parametrize("fixture", [0], indirect=True) + def test_3(self, fixture): + pass + """ + ) + result = pytester.runpytest("-v") + assert result.ret == 0 + result.stdout.fnmatch_lines( + [ + "*test_0*", + "*test_1*", + "*test_2*", + "*test_3*", + ] + ) + class TestMetafuncFunctionalAuto: """Tests related to automatically find out the correct scope for