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).
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