Why does Pytest perform a nested loop over fixture parameters

JafetVoltron :

Using Pytest, I want to write a test function which takes in multiple fixtures as arguments. Each of the fixtures has several parameters.

For example, in test_demo.py is a function test_squared_is_less_than_10 that takes the fixtures, negative_integer and positive_integer as arguments, and then checks that the squared of the fixture parameters is less than 10.

import pytest

@pytest.fixture(params=[-1, -2, -3])
def negative_integer(request):
    return request.param

@pytest.fixture(params=[1, 2, 3])
def positive_integer(request):
    return request.param

def test_squared_is_less_than_10(negative_integer, positive_integer):
    assert negative_integer ** 2 < 10
    assert positive_integer ** 2 < 10

I expect that when I run the pytest command in the terminal, a total of 6 tests should be executed, i.e. [-1, -2, -3] for positive_integer and [1, 2, 3] for negative_integer.

However, pytest seems to executing a nested loop kind of iteration so that 9 tests are executed i.e. [(-1, 1), (-1, 2), (-1, 3), (-2, 1), (-2, 2), (-2, 3), (-3, 1), (-3, 2), (-3, 3)].

Here is the output when I run pytest -v -k "test_squared_is_less":

test_squared_is_less_than_10[-1-1] PASSED                                                              
test_squared_is_less_than_10[-1-2] PASSED                                                              
test_squared_is_less_than_10[-1-3] PASSED                                                              
test_squared_is_less_than_10[-2-1] PASSED                                                              
test_squared_is_less_than_10[-2-2] PASSED                                                              
test_squared_is_less_than_10[-2-3] PASSED                                                              
test_squared_is_less_than_10[-3-1] PASSED                                                              
test_squared_is_less_than_10[-3-2] PASSED                                                              
test_squared_is_less_than_10[-3-3] PASSED 

This is undesirable, as I only want to carry out 6 tests instead of 9. With a larger number of params (say 20), pytest will execute 400 tests instead of the desired 40 tests, which is a waste of computational time.

How can I deal with this problem.

P.S: I would like to avoid writing two separate tests, such as

test_negative_squared_is_less_than_10(negative_integer) and test_positive_squared_is_less_than_10(positive_integer)

hoefling :

You can apply non-cartesian parametrization via the @pytest.mark.parametrize marker. Your code, refactored:

import pytest


neg_params = [-1, -2, -3]

@pytest.fixture(params=neg_params)
def negative_integer(request):
    return request.param


pos_params = [1, 2, 3]

@pytest.fixture(params=pos_params)
def positive_integer(request):
    return request.param


@pytest.mark.parametrize(
    "negative_integer, positive_integer",
    zip(neg_params, pos_params),
    indirect=True
)
def test_squared_is_less_than_10(negative_integer, positive_integer):
    assert negative_integer ** 2 < 10
    assert positive_integer ** 2 < 10

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=360382&siteId=1