'Is there a way to run a test function with multi-return-value fixture?

I have a test that I want to parametrize:

@pytest.mark.parametrize("param", [1,2])
def test(param):
    assert param==1

Now, if I want to have the "param" to have complex logic, I can do:

def f():
    return 1

def g(): # something dumb just to make a point
    for _ in range(100):
        pass
    return 1

@pytest.mark.parametrize("param", [f(), g()])
def test(param):
    assert param==1

However, this would run the "setup" functions before the test runs, i.e.

  1. f()
  2. g()
  3. test value of f()
  4. test value of g()

I tried to have it as a multi-return-value fixture:

@pytest.fixture
def param():
    for i in "12":
        yield i

def test(param):
    assert param==1

but this is illegal (breaks on teardown), so now I imagine something like the parametrize I showed, but with steps 2 & 3 swap the order so I have 2 stand-alone tests.

Is it possible?



Solution 1:[1]

One possibility is to use indirect parametrization to defer the actual function call to a fixture called at runtime (as opposed to the parameters that are evaluated at load time). In your case, you could use the callables as parameters:

@pytest.fixture
def param(request):
    fct = request.param  # f or g
    yield fct()


@pytest.mark.parametrize("param", [f, g], indirect=True)
def test(param):
    assert param == 1

In this case, each function would be called just before the respective test is executed.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 MrBean Bremen