Rodger Shleming
Rodger Shleming

Reputation: 165

Pytest skip with parametrize

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

Answers (1)

hoefling
hoefling

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

Related Questions