Skip to content

Commit

Permalink
fix pytest-dev#10447 - consider marks in reverse mro order to give ba…
Browse files Browse the repository at this point in the history
…se classes priority
  • Loading branch information
RonnyPfannschmidt committed Jul 1, 2023
1 parent 2f7415c commit c207f7c
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 2 deletions.
2 changes: 2 additions & 0 deletions changelog/10447.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
markers are now considered in the reverse mro order to ensure base class markers are considered first
this resolves a regression.
4 changes: 3 additions & 1 deletion src/_pytest/mark/structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,9 @@ def get_unpacked_marks(
if not consider_mro:
mark_lists = [obj.__dict__.get("pytestmark", [])]
else:
mark_lists = [x.__dict__.get("pytestmark", []) for x in obj.__mro__]
mark_lists = [
x.__dict__.get("pytestmark", []) for x in reversed(obj.__mro__)
]
mark_list = []
for item in mark_lists:
if isinstance(item, list):
Expand Down
37 changes: 36 additions & 1 deletion testing/test_mark.py
Original file line number Diff line number Diff line change
Expand Up @@ -1130,6 +1130,41 @@ class C(A, B):

all_marks = get_unpacked_marks(C)

assert all_marks == [xfail("c").mark, xfail("a").mark, xfail("b").mark]
assert all_marks == [xfail("b").mark, xfail("a").mark, xfail("c").mark]

assert get_unpacked_marks(C, consider_mro=False) == [xfail("c").mark]


# @pytest.mark.issue("https://github.com/pytest-dev/pytest/issues/10447")
def test_mark_fixture_order_mro(pytester: Pytester):
"""This ensures we walk marks of the mro starting with the base classes
the action at a distance fixtures are taken as minimal example from a real project
"""
foo = pytester.makepyfile(
"""
import pytest
@pytest.fixture
def add_attr1(request):
request.instance.attr1 = object()
@pytest.fixture
def add_attr2(request):
request.instance.attr2 = request.instance.attr1
@pytest.mark.usefixtures('add_attr1')
class Parent:
pass
@pytest.mark.usefixtures('add_attr2')
class TestThings(Parent):
def test_attrs(self):
assert self.attr1 == self.attr2
"""
)
result = pytester.runpytest(foo)
result.assert_outcomes(passed=1)

0 comments on commit c207f7c

Please sign in to comment.