Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Use pytest.mark.parametrize both directly and indirectly

Using pytest, how can I parametrise a test function and then use the value both directly and indirectly?

For example, take the very basic test below to check that a function to square a number returns the correct value. As far as I know, I have to parameterise the test function with the same set of arguments twice – once directly and once indirectly.

However, because pytest runs all possible combinations of parameters, this means that the test function fill pass twice (1-1 and 2-2) and fail twice (1-2 and 2-1).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Is there a way to see the parameter value passed to the square_number fixture in the test function as well?


Example code

import pytest

def calculate_square(num: int):
    return num ** 2

args = [1,2]

@pytest.mark.parametrize('number', args)
class TestSomething:

    @pytest.fixture(scope='module')
    def square_number(self, request):
        yield calculate_square(request.param)

    @pytest.mark.parametrize('square_number', args, indirect=True)
    def test_first_thing(self, number, square_number):
        assert number ** 2 == square_number

Example code results

q.py::TestSomething::test_first_thing[1-1] PASSED
q.py::TestSomething::test_first_thing[1-2] FAILED
q.py::TestSomething::test_first_thing[2-1] FAILED
q.py::TestSomething::test_first_thing[2-2] PASSED

Desired code


    @pytest.mark.parametrize('square_number', args, indirect=True)
    def test_first_thing(self, square_number):
        number = ??? # Somehow get current 'args' value from 'square_number'
        assert number ** 2 == square_number

Desired results

q.py::TestSomething::test_first_thing[1] PASSED
q.py::TestSomething::test_first_thing[2] PASSED

>Solution :

Unless I’m missing something here, why do you need indirect parametrization at all?

import pytest


@pytest.mark.parametrize(
    'number, expected',
    [  # this could be `[(x, x ** 2) for x in (1, 2)]`
        (1, 1),
        (2, 4),
    ],
)
def test_square(number, expected):
    assert number ** 2 == expected

You can of course also return a tuple from the fixture and unpack it:

import pytest


@pytest.fixture()
def square_number(request):
    return (request.param, request.param ** 2)


@pytest.mark.parametrize(
    'square_number',
    [1, 2],
    indirect=True,
)
def test_square(square_number):
    number, expected = square_number
    assert number ** 2 == expected
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading