You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Parent class marked fixture no longer reached with pytest 7.2 #10447
The fixture on the subclass is reliant on the prior execution of the fixture in the parent class.
See the upstream bug for:
a detailed description of the bug or problem you are having
output of pip list from the virtual environment you are using
pytest and operating system versions
For consideration:
minimal example if possible
I haven't put together a minimal example yet as I'm still triaging the issue. Is there a known change with pytest 7.2 that was expected to change this behavior?
To be sure, these tests deserve a refactor. The tests are in this state because the project is transitioning away from unittest, but some artifacts remain.
Probably plugin:unittest is not relevant here, because the class hierarchy is no longer based on unittest.TestCase. I mention unittest because it explains why the fixtures reference request.instance as self (an artifact of the expectation when they did rely on TestCase).
The MRO refactor was #7792 (31df38f). I've confirmed that the distutils fail on 31df38f but pass on 31df38f^1, confirming that change is the culprit.
The changelog says:
When inheriting marks from super-classes, the pytestmark attribute of the sub-class now only contains the marks directly applied to it. Previously, it also contained marks from its super-classes.
That implies that it's intentional that previously reachable marks are now intentionally ignored.
I'm not sure why that wouldn't be a breaking change.
Is there any chance pytest will restore support for this use-case? Is there a way to apply a fixture at a superclass and have it take effect in a subclass?
draft @ pip-run 'pytest@git+https://github.com/pytest-dev/pytest@31df38f6a79b0734be3c1386eb7df6512b1a321b^1' -- -m pytest
WARNING: Did not find branch or tag '31df38f6a79b0734be3c1386eb7df6512b1a321b^1', assuming revision or ref.
========================================================================= test session starts ==========================================================================
platform darwin -- Python 3.11.4, pytest-7.2.0.dev331+g15ac0349, pluggy-1.2.0
rootdir: /Users/jaraco/draft
plugins: anyio-3.6.2
collected 1 item
test_something.py . [100%]
========================================================================== 1 passed in 0.00s ===========================================================================
draft @ pip-run 'pytest@git+https://github.com/pytest-dev/pytest@31df38f6a79b0734be3c1386eb7df6512b1a321b' -- -m pytest
========================================================================= test session starts ==========================================================================
platform darwin -- Python 3.11.4, pytest-7.2.0.dev338+g31df38f6, pluggy-1.2.0
rootdir: /Users/jaraco/draft
plugins: anyio-3.6.2
collected 1 item
test_something.py E [100%]
================================================================================ ERRORS ================================================================================
_______________________________________________________________ ERROR at setup of TestThings.test_attrs ________________________________________________________________
request = <SubRequest 'add_attr2' for <Function test_attrs>>
@pytest.fixture
def add_attr2(request):
> request.instance.attr2 = request.instance.attr1
E AttributeError: 'TestThings' object has no attribute 'attr1'
test_something.py:10: AttributeError
======================================================================= short test summary info ========================================================================
ERROR test_something.py::TestThings::test_attrs - AttributeError: 'TestThings' object has no attribute 'attr1'
=========================================================================== 1 error in 0.02s ===========================================================================
The issue isn't that the fixture on the parent class isn't being called, but that the fixtures are called in a different order with the fixture on the child being called before the fixture on the parent. Independent of this specific example, I'd expect fixtures on more basic classes to be called first, as the child (derived) class is liable to depend on behavior from the parent but not vice-versa (from a modeling perspective, the parent class is largely unaware of the child classes).
Activity
jaraco commentedon Oct 29, 2022
To be sure, these tests deserve a refactor. The tests are in this state because the project is transitioning away from unittest, but some artifacts remain.
jaraco commentedon Oct 29, 2022
Probably
plugin:unittestis not relevant here, because the class hierarchy is no longer based onunittest.TestCase. I mention unittest because it explains why the fixtures referencerequest.instanceasself(an artifact of the expectation when they did rely onTestCase).RonnyPfannschmidt commentedon Oct 29, 2022
this may be related to extraction of marks from the mro, (dint happenbefore, was aded recently
jaraco commentedon Jul 1, 2023
The MRO refactor was #7792 (31df38f). I've confirmed that the distutils fail on 31df38f but pass on 31df38f^1, confirming that change is the culprit.
The changelog says:
That implies that it's intentional that previously reachable marks are now intentionally ignored.
I'm not sure why that wouldn't be a breaking change.
Is there any chance pytest will restore support for this use-case? Is there a way to apply a fixture at a superclass and have it take effect in a subclass?
RonnyPfannschmidt commentedon Jul 1, 2023
The markers should take effect as all of them should land in the node for the class, I'll have to investigate the order difference
jaraco commentedon Jul 1, 2023
In that case, let me put together a more minimal repro.
jaraco commentedon Jul 1, 2023
Good news. A minimal repro was easy and I learned something:
The issue isn't that the fixture on the parent class isn't being called, but that the fixtures are called in a different order with the fixture on the child being called before the fixture on the parent. Independent of this specific example, I'd expect fixtures on more basic classes to be called first, as the child (derived) class is liable to depend on behavior from the parent but not vice-versa (from a modeling perspective, the parent class is largely unaware of the child classes).
RonnyPfannschmidt commentedon Jul 1, 2023
Found the bug
https://github.com/pytest-dev/pytest/blob/main/src/_pytest/mark/structures.py#L377 is missing a reversed when considering the mro
Reverse order on marks from MRO
fix pytest-dev#10447 - consider marks in reverse mro order to give ba…
fix pytest-dev#10447 - consider marks in reverse mro order to give ba…
RonnyPfannschmidt commentedon Jul 1, 2023
@jaraco seems like our timing was unfortuate
jaraco commentedon Jul 1, 2023
No problem. Happy to consolidate. I'll fix the mypy bug in mine and copy the test from yours, but feel free to choose the PR you prefer.
Reverse order on marks from MRO
RonnyPfannschmidt commentedon Jul 1, 2023
@jaraco im under the impression that the content would practically be the same, so i'd just go with mine
fix pytest-dev#10447 - consider marks in reverse mro order to give ba…
Merge pull request #11155 from RonnyPfannschmidt/fix-10447-maker-mro-…
[7.4.x] fix #10447 - consider marks in reverse mro order to give base…
[7.4.x] fix #10447 - consider marks in reverse mro order to give base…
fix pytest-dev#10447 - consider marks in reverse mro order to give ba…
fix pytest-dev#10447 - consider marks in reverse mro order to give ba…
fix pytest-dev#10447 - consider marks in reverse mro order to give ba…