-
Notifications
You must be signed in to change notification settings - Fork 28
Test with parametrize items ; how to repeat but launch fixture only between batch of test? #48
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
Comments
That's currently not possible |
Thank you for your prompt answer. I'll leave you to decide whether to close or let this issue open. |
Digging this one out. A way to trigger this, I think, would be to add a This could be provided as a non Regarding plugin implementation, there is maybe a way to, from outside, add an argument to a fixture in the same way as its done for the functions Could be interesting to have this for cases where |
I have a similar request as @ggrelet . I have a time-expensive configuration procedure for my system under test, and it seemed appropriate to execute this configuration in a session-scoped fixture, say @pytest.fixture(scope="session")
def expensive_configuration():
important_results = do_the_things()
return important_results This is exactly what I think @cladmi is thinking about when they say "cases where The fixture works well, for a single pass through the tests: Any subset of tests can be run in any order, and as they all declare However, in trying to use Trying @cladmi's suggestion above seemed promising; however, it results (unsurprising in hindsight) in an error: @pytest.fixture(scope="session")
def expensive_configuration(__pytest_repeat_step_number):
important_results = do_the_things()
return important_results and, of course, it always feels wrong (one might say, is wrong?) to leverage double-underscored objects. Then again, I might be misinterpreting the suggestion or overlooking something else obvious. Please correct me if I've missed something! I somewhat wonder if the idea is at odds with the way |
May bad, you are correct, as One solution, with a code change in the plugin, would be to declare it with a dynamic scope.
Then Regarding the current implementation on how it is done, the fixture is enabled as if it was declared It is still the main way of duplicating tests, it is like a global |
I have a work-around in mind. It suits my needs a bit better than, perhaps, the needs of the OP, because I care about triggering when a test requires a new configuration, while they seem to be looking for cleanup once any particular parameterization is complete. Without more specific description of the problem, I don't think I could give a better answer, but I think this technique is fairly flexible (or a janky hack? (-: ) and could be tweaked to probably satisfy the needs of the OP's situation, even if it's not the cleanest. With this code import pytest
@pytest.mark.repeat(3)
@pytest.mark.parametrize("case", ["a","b","c"])
def test_1(case, my_fixture):
print("test_1 case: {}".format(case))
@pytest.fixture(scope="function")
def my_fixture():
yield # Executed at the end of the test
print("\nmy_fixture") I was able to essentially recreate the behavior described by the OP. With this code, I was able to mock the desired behavior. # scope_issues/scope_test.py
import pytest
@pytest.mark.repeat(3)
@pytest.mark.parametrize("case", ["a","b","c"])
def test_1(case, my_fixture):
print("test_1 case: {}".format(case))
seen_counts = set()
@pytest.fixture(scope="function")
def my_fixture(request, final_cleanup):
global seen_counts
test_count = count_from_name(request)
if not seen_counts or test_count in seen_counts:
seen_counts.add(test_count)
# mocking "session" scope by bailing at this point
# Either the first round or a repeat, so we do nothing.
return
else:
# This is the first of a new parameterization, and
# we should clean up from the last one.
seen_counts.add(test_count)
important_work()
@pytest.fixture(scope="session")
def final_cleanup():
yield
important_work()
def important_work():
print("\nmy_fixture")
def count_from_name(request) -> str:
test_name = request.node.name
test_param_suffix = test_name.split("[")[-1].strip("]")
test_count = "-".join(test_param_suffix.split("-")[-2:])
# Test count is something like "3-5"
return test_count Thoughts? |
Output from hacky code:
|
I do like @cladmi's idea of scoping I don't think I, personally, will be able to use any plugin code change for my project, and I'm relatively happy with how I can flexibly handle things this way. (Test fixture could be tightened:) @pytest.fixture(scope="function")
def my_fixture(request, final_cleanup):
global seen_counts
test_count = count_from_name(request)
if seen_counts and test_count not in seen_counts:
# We've seen test code, but this is new test code,
# and we need to clean up before it executes.
important_work()
seen_counts.add(test_count) |
I believe this would be solved by a missing scopes of pytest fixtures, namely "parametrize" scope. |
this really requires a change to pytest, so closing the issue |
@okken the function definition scope already exists, the refactoring to have it Part of the collection tree is missing |
@RonnyPfannschmidt That's cool. Is that planned to be added to the collection tree anytime soon-ish? like 2024 sometime? or a "maybe someday"? |
Currently it's a maybe sometime, I hope we can create a working version at the Sprint Unfortunately function is quite the spaghetti monster, once the ctor refactoring is complete it as should be simpler |
I was hoping to get some Experiments this week but I'm completely down with a bad cold/flu and chills |
Well. I'm glad it's on the radar. Also, sorry you're feeling crummy. |
I have a simple test with parametrize and fixture:
Which
pytest-repeat
scope andpytest
scope should I use if I want the following output?So far I managed to have the following:
1- With
pytest-repeat
'sscope="session"
andpytest
'sscope="session"
2- With
pytest-repeat
'sscope="session"
andpytest
'sscope="function"
Thanks for your help.
The text was updated successfully, but these errors were encountered: