Reputation: 165
When using pytest.mark.skip
with pytest.mark.parametrize
python evaluates the parametrize
parameters inspite of the skip
function (obviously):
import pytest
def get_params():
# Do super heavy and slow logic to get parameters
print("Params function called!")
return (1, 2)
@pytest.mark.skip()
@pytest.mark.parametrize("a, b", [get_params()])
def test_foo(a, b):
pass
In that example I always skip the test_foo
test function, I got another function called get_params
to get the parameters for the test function.
The get_params
is very complicated and I don't want to call it if I know I'm going to skip the test.
If I run the test, I can see the print "Params function called!" meaning that the get_params
function called.
I know this happens because of python evaluation order, and the get_params
function called before the skip got to to its thing.
Because of that I have tried using generators:
import pytest
def get_params():
# Do super heavy and slow logic to get parameters
print("Params function called!")
return (1, 2)
def get_generator():
yield get_params()
@pytest.mark.skip()
@pytest.mark.parametrize("a, b", get_generator())
def test_foo(a, b):
pass
But the results are the same.
How can I make get_params
function not to be called if skip
was provided?
Upvotes: 2
Views: 1410
Reputation: 66461
This won't be possible using the mark.parametrize
marker, it is always evaluated. However, you can move the parametrization to the pytest_generate_tests
hookimpl. Create a conftest.py
file in your test or project root dir with the contents:
def get_params():
...
def pytest_generate_tests(metafunc):
# check if skip marker applied
if metafunc.definition.get_closest_marker('skip') is not None:
return
# check if test requests a and b args
if all(name in metafunc.definition.fixturenames for name in ('a', 'b')):
metafunc.parametrize('a,b', [get_params()])
Any test requesting a
and b
args will now be parametrized if not skipped via marker.
Upvotes: 2