Ashley
Ashley

Reputation: 13

Indirect fixture doesn't exist when parametrising tests with fixtures

I'm using pytest and I'm trying to pass a fixture as a value in a parametrised test. I read the documentation for parametrised tests and the indirect = True parameter, but when I try to run it I keep getting an error message. I require the fixtures of different objects for different tests and I have the code below:

#in user.py

class User(object):
    def __init__(self, first_name: str, last_name: str):
        self.first_name = first_name
        self.last_name = last_name

    def create_full_name(self):
        return f'{self.first_name} {self.last_name}'

#in conftest.py

@pytest.fixture(scope='function')
def normal_user():
    '''Returns a normal user'''
    normal_user = user.User(first_name = 'katherine', last_name = 'rose')
    yield normal_user

@pytest.fixture(scope='function')
def missing_details():
    '''Returns a user without a last name'''
    missing_details = user.User(first_name = ' ', last_name = 'rose')
    yield missing_details

#in test_user.py

@pytest.mark.parametrize('user, expected', [('normal_user', 'katherine rose'), ('missing_details', TypeError)], indirect= ['normal_user', 'missing_details'])
def test_parametrize_user_full_name(user, expected):
    assert user.create_full_name(user) == expected

The error message I keep getting is: In test_parametrize_user_full_name: indirect fixture 'normal_user' doesn't exist

Is it necessary to specify which fixtures should be indirect in conftest.py or am I writing the code for the parametrised test incorrectly?

Upvotes: 0

Views: 2423

Answers (1)

MrBean Bremen
MrBean Bremen

Reputation: 16815

This is not how indirect parametrization works. You have to reference one fixture with the indirect parameter, and the fixture will return the actual value based on the value in the parameter value list. You can find an example in the documentation.

In your case you would need something like:

@pytest.fixture
def user(request):
    if request.param == 'normal_user':
        # Returns a normal user
        yield User(first_name='katherine', last_name='rose')
    if request.param == 'missing_details':
        # Returns a user without a last name
        yield User(first_name=' ', last_name='rose')


@pytest.mark.parametrize('user, expected', [('normal_user', 'katherine rose'),
                                            ('missing_details', TypeError)],
                         indirect=['user'])
def test_parametrize_user_full_name(user, expected):
    ...

As an aside: comparing the result against an exception will not work the way you do it, but I guess this is only a dumbed down example that is not expected to work.

Upvotes: 2

Related Questions