Fixture execution order: higher-scoped fixtures are not necessarily run before lower-scoped fixtures #2405
I've encountered what appears to be a violation of the expectation that higher-scoped fixtures are run before lower scoped fixtures.
In conftest.py, I have a module-scoped fixture.
In the test suite, I wish to reference that fixture:
And an autouse test at the class scope:
But when the tests run, it appears that
I was able to work around the issue by removing the pytestmark and instead specifying
If this fixture execution order is by design, is there a better way to achieve what I'm after (essentially the
The text was updated successfully, but these errors were encountered:
I believe it is a bug, I also would expect the same behavior you describe.
Actually according to this code it should be doing that already, so it's definitely a bug IMO.
Turns out I was able to make a replication script from the description above:
Adding a no-op test before the TestDataValues works around the issue:
Did some more digging, sorry for the delay.
The culprit IIUC is how mark transfer works (@RonnyPfannschmidt will love this).
In other words,
@pytest.mark.usefixtures('clean_data') def test_value(self):
Which is equivalent to:
def test_value(self, clean_data):
(btw you mention that the above fixes the issue for you, but I obtain the same error in my tests)
def test_value(self, add_data, clean_data):
Which explains the behavior: first data is added and right afterwards removed, so the test fails.
Now if you change the
So it all boils down to how markers are currently transferred. @RonnyPfannschmidt is leading a quest to sort all this marker business out and remove the marker transfer mechanism to an approach where the markers are attached to the collection node instead, so you don't lose the marker hierarchy when marking classes and
Back to the workaround, I realize that
@pytest.mark.fixture(session='module', autouse=True) def _clean_data(clean_data): pass
This will attach the "autouse" fixture to the module node, which is what one would expect that
@RonnyPfannschmidt if you agree with my diagnosis, I believe we should label this as
I got a similar issue with pytest-django. However IMO this is caused by pytest. I can also open a new issue for this one. Just let me know if you don't think they are related.
This is the test code:
And this the result:
IMO this should never happen. The session fixtures should always be executed first, otherwise you can have big problems with e.g. transactions, especially if used with autouse. However it's also worth noting that I think in general the execution order should be session fixtures first, even if specified in another order. It only makes sense if you think about it. The session fixture might already have been used by another test function.
@nicoddemus i came to the conclusion that this is more likely a fixture issue, because we sort autouse ixtures first, even thos the scopes require a different order - it shouldnt matter where the usage is defined - a fixture with a higher scope should be executed first
@jaraco I just realized a workaround for your original problem, just change your
@pytest.fixture(scope='module') def clean_data(): yield data.clear()
Well, no. The intention is to ensure before a test is run that no state lingers from a previous test, possibly from another module. But probably is a better design to remove the state as a teardown operation.
I appreciate the work on this as it appears to be both subtle and tricky.