Rajat Bhardwaj
Rajat Bhardwaj

Reputation: 169

Can we call a pytest fixture conditionally?

My use case is to call fixture only if a certain condition is met. But since we need to call the pytest fixture as an argument to a test function it gets called every time I run the test.

I want to do something like this:

@pytest.parameterize("a", [1, 2, 3])
def test_method(a):
    if a == 2:
       method_fixture

Upvotes: 5

Views: 6914

Answers (2)

tomako
tomako

Reputation: 3879

The answer is accepted and helped for the OP however it is not "conditional fixture calling". It is called always only it behaves differently based on some condition.

So I only want to clarify that real conditionally call (or dynamically run) a fixture is possible using the request fixture.

@pytest.parameterize("a", [1, 2, 3])
def test_method(request, a):
    if a == 2:
        request.getfixturevalue('method_fixture')

See documentation here https://docs.pytest.org/en/7.1.x/reference/reference.html#pytest.FixtureRequest.getfixturevalue

Upvotes: 13

AKX
AKX

Reputation: 168957

Yes, you can use indirect=True for a parameter to have the parameter refer to a fixture.

import pytest


@pytest.fixture
def thing(request):
    if request.param == 2:
        return func()
    return None


@pytest.mark.parametrize("thing", [1, 2, 3], indirect=True)
def test_indirect(thing):
    pass  # thing will either be the retval of `func()` or NOne

With dependent "fixtures"

As asked in the edit, if your fixtures are dependent on each other, you'll probably need to use the pytest_generate_tests hook instead.

E.g. this will parametrize the test with values that aren't equal.

import itertools


def pytest_generate_tests(metafunc):
    if metafunc.function.__name__ == "test_combo":
        a_values = [1, 2, 3, 4]
        b_values = [2, 3, 4, 5]
        all_combos = itertools.product(a_values, b_values)
        combos = [
            pair
            for pair in all_combos
            if pair[0] != pair[1]
        ]
        metafunc.parametrize(["a", "b"], combos)


def test_combo(a, b):
    assert a != b

Upvotes: 4

Related Questions