From a6851e3459159f94387debf0b357c9b6481a2f48 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 13 Feb 2024 09:44:13 +0200 Subject: [PATCH] [8.0.x] main: fix reversed collection order in Session --- changelog/11937.bugfix.rst | 1 + src/_pytest/main.py | 2 +- testing/acceptance_test.py | 2 +- testing/test_collection.py | 21 +++++++++++++++++++-- 4 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 changelog/11937.bugfix.rst diff --git a/changelog/11937.bugfix.rst b/changelog/11937.bugfix.rst new file mode 100644 index 00000000000..3b15fb528e9 --- /dev/null +++ b/changelog/11937.bugfix.rst @@ -0,0 +1 @@ +Fix a regression in pytest 8.0.0 whereby items would be collected in reverse order in some circumstances. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 0a0df070f9c..f1c05754b2f 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -898,7 +898,7 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: # Prune this level. any_matched_in_collector = False - for node in subnodes: + for node in reversed(subnodes): # Path part e.g. `/a/b/` in `/a/b/test_file.py::TestIt::test_it`. if isinstance(matchparts[0], Path): is_match = node.path == matchparts[0] diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 798c153ffcc..defc2bc2557 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -240,7 +240,7 @@ def test_issue88_initial_file_multinodes(self, pytester: Pytester) -> None: pytester.copy_example("issue88_initial_file_multinodes") p = pytester.makepyfile("def test_hello(): pass") result = pytester.runpytest(p, "--collect-only") - result.stdout.fnmatch_lines(["*Module*test_issue88*", "*MyFile*test_issue88*"]) + result.stdout.fnmatch_lines(["*MyFile*test_issue88*", "*Module*test_issue88*"]) def test_issue93_initialnode_importing_capturing(self, pytester: Pytester) -> None: pytester.makeconftest( diff --git a/testing/test_collection.py b/testing/test_collection.py index 1cb553e5066..b2780eb73ae 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -591,12 +591,12 @@ def pytest_collect_file(file_path, parent): hookrec.assert_contains( [ ("pytest_collectstart", "collector.path == collector.session.path"), - ("pytest_collectstart", "collector.__class__.__name__ == 'Module'"), - ("pytest_pycollect_makeitem", "name == 'test_func'"), ( "pytest_collectstart", "collector.__class__.__name__ == 'SpecialFile'", ), + ("pytest_collectstart", "collector.__class__.__name__ == 'Module'"), + ("pytest_pycollect_makeitem", "name == 'test_func'"), ("pytest_collectreport", "report.nodeid.startswith(p.name)"), ] ) @@ -670,6 +670,23 @@ def test_method(self): # ensure we are reporting the collection of the single test item (#2464) assert [x.name for x in self.get_reported_items(hookrec)] == ["test_method"] + def test_collect_parametrized_order(self, pytester: Pytester) -> None: + p = pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize('i', [0, 1, 2]) + def test_param(i): ... + """ + ) + items, hookrec = pytester.inline_genitems(f"{p}::test_param") + assert len(items) == 3 + assert [item.nodeid for item in items] == [ + "test_collect_parametrized_order.py::test_param[0]", + "test_collect_parametrized_order.py::test_param[1]", + "test_collect_parametrized_order.py::test_param[2]", + ] + class Test_getinitialnodes: def test_global_file(self, pytester: Pytester) -> None: