-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixture execution order: higher-scoped fixtures are not necessarily run before lower-scoped fixtures #2405
Comments
I'm using pytest 3.0.7. |
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. |
Okay. Thanks for the review. I think I owe you a reproducible sample. I'll work on that next. |
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:
Or adding |
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 |
@nicoddemus i wont be able o fllow any in deepth diagnois tasks the next 2 weeks - but i trust your judgement |
Hooray. 😁
OK I will change the labels, you can revisit this whenever you have the time. |
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 |
Is this going to be fixed? |
@pavelrad If someone finds the time to work on it, sure - are you volunteering? 😉 |
I still hope (fingers crossed) that this is related to marks so when we land the full mark refactoring this will be solved, otherwise we will need to find some time to investigate this further. |
@nicoddemus i believe its related to fixtures only |
Hmm I see, so you think just sorting autouse fixtures by scope would be sufficient in this case? |
off hand no idea, im currently not fluent in that bit of the codebase - i recall the last time we tried to change something there ended horrible |
@jaraco I just realized a workaround for your original problem, just change your @pytest.fixture(scope='module')
def clean_data():
yield
data.clear() IOW, make |
Btw: the original assumption that higher-scoped fixtures should run before lower-scoped ones is still valid and should be fixed (I updated the title of the issue to reflect that). |
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. |
I see thanks! |
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
add_data
runs beforeclean_data
. Perhaps that's because of the autouse feature. Is that expected for all autouse fixtures to be run before marked fixtures even when the autouse is at a finer scope?I was able to work around the issue by removing the pytestmark and instead specifying
clean_data
as a parameter to eachadd_data
across several classes in the module. I don't like this workaround because it violates the goal of signaling the cleanup exactly once at the beginning of the module (akin to asetup_module
method).If this fixture execution order is by design, is there a better way to achieve what I'm after (essentially the
setup_module
andsetup_class
behavior from unittest)?The text was updated successfully, but these errors were encountered: