Skip to content

Commit 44ad1c9

Browse files
[7.4.x] fix #10447 - consider marks in reverse mro order to give base classes priority (#11545)
Co-authored-by: Ronny Pfannschmidt <[email protected]>
1 parent 5dc7725 commit 44ad1c9

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
lines changed

changelog/10447.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
markers are now considered in the reverse mro order to ensure base class markers are considered first
2+
this resolves a regression.

src/_pytest/mark/structures.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,9 @@ def get_unpacked_marks(
373373
if not consider_mro:
374374
mark_lists = [obj.__dict__.get("pytestmark", [])]
375375
else:
376-
mark_lists = [x.__dict__.get("pytestmark", []) for x in obj.__mro__]
376+
mark_lists = [
377+
x.__dict__.get("pytestmark", []) for x in reversed(obj.__mro__)
378+
]
377379
mark_list = []
378380
for item in mark_lists:
379381
if isinstance(item, list):

testing/test_mark.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,41 @@ class C(A, B):
11301130

11311131
all_marks = get_unpacked_marks(C)
11321132

1133-
assert all_marks == [xfail("c").mark, xfail("a").mark, xfail("b").mark]
1133+
assert all_marks == [xfail("b").mark, xfail("a").mark, xfail("c").mark]
11341134

11351135
assert get_unpacked_marks(C, consider_mro=False) == [xfail("c").mark]
1136+
1137+
1138+
# @pytest.mark.issue("https://github.com/pytest-dev/pytest/issues/10447")
1139+
def test_mark_fixture_order_mro(pytester: Pytester):
1140+
"""This ensures we walk marks of the mro starting with the base classes
1141+
the action at a distance fixtures are taken as minimal example from a real project
1142+
1143+
"""
1144+
foo = pytester.makepyfile(
1145+
"""
1146+
import pytest
1147+
1148+
@pytest.fixture
1149+
def add_attr1(request):
1150+
request.instance.attr1 = object()
1151+
1152+
1153+
@pytest.fixture
1154+
def add_attr2(request):
1155+
request.instance.attr2 = request.instance.attr1
1156+
1157+
1158+
@pytest.mark.usefixtures('add_attr1')
1159+
class Parent:
1160+
pass
1161+
1162+
1163+
@pytest.mark.usefixtures('add_attr2')
1164+
class TestThings(Parent):
1165+
def test_attrs(self):
1166+
assert self.attr1 == self.attr2
1167+
"""
1168+
)
1169+
result = pytester.runpytest(foo)
1170+
result.assert_outcomes(passed=1)

0 commit comments

Comments
 (0)