Search code examples
pythonunit-testingpytestfixtures

pytest: Parameterized test cases via fixtures


How do you write a fixture (a method) that yields/returns parameterized test parameters?

For instance, I have a test as the following:

@pytest.mark.parametrize(
    "input,expected", 
    [("hello", "hello"),
    ("world", "world")])
def test_get_message(self, input, expected):
    assert expected == MyClass.get_message(input)

Instead of having input and expected to be passed via @pytest.mark.parametrize, I am interested in an approach as the following:

@pytest.fixture(scope="session")
def test_messages(self):
    # what should I write here to return multiple 
    # test case with expected value for each?
    pass

def test_get_message(self, test_messages):
    expected = test_messages["expected"] # somehow extracted from test_messages?
    input = test_messages["input"]       # somehow extracted from test message?
    assert expected == MyClass.get_message(input)

Solution

  • To move the parameters into a fixture, you can use fixture params:

    @pytest.fixture(params=[("hello", "hello"),
        ("world", "world")], scope="session")
    def test_messages(self, request):
        return request.param
    
    def test_get_message(self, test_messages):
        input = test_messages[0]   
        expected = test_messages[1]
        assert expected == MyClass.get_message(input)
    

    You can also put the params into a separate function (same as wih parametrize), e.g.

    def get_test_messages():
        return [("hello", "hello"), ("world", "world")]
    
    @pytest.fixture(params=get_test_messages(), scope="session")
    def test_messages(self, request):
        return request.param