Search code examples
pythonpytestfixtures

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

Solution

  • 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