Reverse order on marks from MRO

Fixes #10447
This commit is contained in:
Jason R. Coombs 2023-07-01 16:04:22 -04:00
parent b77d0deaf5
commit a8eb81994e
No known key found for this signature in database
GPG Key ID: 708E6CB181B4C47E
3 changed files with 41 additions and 3 deletions

View File

@ -0,0 +1 @@
When resolving marks from a class hierarchy MRO, reverse the order so that more basic classes' marks will be processed ahead of ancestral classes.

View File

@ -372,9 +372,11 @@ def get_unpacked_marks(
"""
if isinstance(obj, type):
if not consider_mro:
mark_lists = [obj.__dict__.get("pytestmark", [])]
mark_lists: Iterable[Any] = [obj.__dict__.get("pytestmark", [])]
else:
mark_lists = [x.__dict__.get("pytestmark", []) for x in obj.__mro__]
mark_lists = reversed(
[x.__dict__.get("pytestmark", []) for x in obj.__mro__]
)
mark_list = []
for item in mark_lists:
if isinstance(item, list):

View File

@ -1130,6 +1130,41 @@ def test_mark_mro() -> None:
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)