“ indirect fixture” error using pytest. What is wrong?

Question:

 def fatorial(n):
    if n <= 1:
        return 1
    else:
        return n*fatorial(n - 1)


import pytest

@pytest.mark.parametrize("entrada","esperado",[
    (0,1),
    (1,1),
    (2,2),
    (3,6),
    (4,24),
    (5,120)
])

def testa_fatorial(entrada,esperado):
    assert fatorial(entrada)  == esperado

The error:

 ERROR collecting Fatorial_pytest.py ____________________________________________________________________
In testa_fatorial: indirect fixture '(0, 1)' doesn't exist

I dont know why I got “indirect fixture”. Any idea?
I am using python 3.7 and windows 10 64 bits.

Asked By: Laurinda Souza

||

Answers:

TL;DR
The problem is with the line

@pytest.mark.parametrize("entrada","esperado",[ ... ])

It should be written as a comma-separated string:

@pytest.mark.parametrize("entrada, esperado",[ ... ])

You got the indirect fixture because pytest couldn’t unpack the given argvalues since it got a wrong argnames parameter. You need to make sure all parameters are written as one string.

Please see the documentation:

The builtin pytest.mark.parametrize decorator enables parametrization of arguments for a test function.

Parameters:
1. argnames – a comma-separated string denoting one or more argument names, or a list/tuple of argument strings.
2. argvalues – The list of argvalues determines how often a test is invoked
with different argument values.

Meaning, you should write the arguments you want to parametrize as a single string and separate them using a comma. Therefore, your test should look like this:

@pytest.mark.parametrize("n, expected", [
    (0, 1),
    (1, 1),
    (2, 2),
    (3, 6),
    (4, 24),
    (5, 120)
])
def test_factorial(n, expected):
    assert factorial(n) == expected
Answered By: Matan Itzhak

For anyone else who ends up here for the same reason I did, if you’re labeling your tests with a list of ids, the ids list must be a named parameter like so:

@pytest.mark.parametrize("arg1, arg2", paramlist, ids=param_ids)

instead of

@pytest.mark.parametrize("arg1, arg2", paramlist, param_ids)
Answered By: zeusalmighty

I got a similar error from omitting the square brackets around the parameter values, e.g.

@pytest.mark.parametrize('task_status', State.PENDING,
                                         State.PROCESSED,
                                         State.FAILED)

Gives the error ‘indirect fixture ‘P’ doesn’t exist’. The fix:

@pytest.mark.parametrize('task_status', [State.PENDING,
                                         State.PROCESSED,
                                         State.FAILED])
Answered By: Oli