简体   繁体   中英

Pytest parametrize a test using a fixture

I am trying to better understand how to thoroughly unit test using pytest and came across a situation that I am not sure how to best approach. I found similar questions here on SO about parameterizing fixtures themselves but I don't think that is what I want to do here. But maybe I am not fully understanding fixtures themselves?

Here is some sample code:

App Code:

class Person:
    def __init__(self, fname: str, lname: str):
        self.fname = fname
        self.lname = lname

    def upper_fullname(self):
        return f'{self.fname} {self.lname}'.upper()

Tests:

import pytest

@pytest.fixture(scope="module")
def fixture_mm(conf={"fname": "mickey", "lname": "mouse"}):
    return Person(**conf)

@pytest.fixture(scope="module")
def fixture_bb(conf={"fname": "bugs", "lname": "bunny"}):
    return Person(**conf)

@pytest.mark.parametrize(
    'person, expected_result',
    [(fixture_mm, "MICKEY MOUSE"), (fixture_bb, "BUGS BUNNY")])
def test_uppernames(person, expected_result):
    assert person.upper_fullname() == expected_result

I would expect both of these tests to pass but instead I get an error message saying AttributeError: 'function' object has no attribute 'upper_fullname' . What am I missing here?

Thanks.

You're getting an error because fixture_mm is a function. You need to call a function to get a value ( fixture_mm() ), but this is not going to work with fixtures.

But I don't think you even need fixtures here. You could make these into normal functions and use them like this:

def person_mm(conf={"fname": "mickey", "lname": "mouse"}):
    return Person(**conf)

def person_bb(conf={"fname": "bugs", "lname": "bunny"}):
    return Person(**conf)

@pytest.mark.parametrize(
    'person, expected_result',
    [(person_mm(), "MICKEY MOUSE"), (person_bb(), "BUGS BUNNY")])
def test_uppernames(person, expected_result):
    assert person.upper_fullname() == expected_result

Caveat: since fixture parameters are evaluated at the module compile time, this might cause issues if the functions require some setup. On the other hand, if your functions are as simple as in this example, you could even save these objects as constants:

PERSON_MM = Person(fname="mickey", lname="mouse")
PERSON_BB = Person(fname="bugs", lname="bunny")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM