为什么 Pytest 对夹具参数执行嵌套循环
Why does Pytest perform a nested loop over fixture parameters
我想使用 Pytest 编写一个测试函数,它接受多个固定装置作为参数。每个灯具都有几个参数。
例如,在test_demo.py中有一个函数test_squared_is_less_than_10
,它以夹具negative_integer
和positive_integer
作为参数,然后检查夹具的平方参数小于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
我希望当我在终端中 运行 pytest 命令时,总共应该执行 6 个测试,即 [-1, -2, -3]
用于 positive_integer
和 [1, 2, 3]
用于negative_integer
.
但是,pytest 似乎执行了一种嵌套循环迭代,因此执行了 9 个测试
即 [(-1, 1), (-1, 2), (-1, 3), (-2, 1), (-2, 2), (-2, 3), (-3, 1), (-3, 2), (-3, 3)]
.
这是我 运行 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
这是不可取的,因为我只想执行 6 个测试而不是 9 个。如果参数数量较多(例如 20 个),pytest 将执行 400 个测试而不是所需的 40 个测试,这是浪费计算时间。
我该如何处理这个问题。
P.S:我想避免写两个单独的测试,比如
test_negative_squared_is_less_than_10(negative_integer)
和 test_positive_squared_is_less_than_10(positive_integer)
您可以通过 @pytest.mark.parametrize
标记应用非笛卡尔参数化。您的代码,已重构:
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
我想使用 Pytest 编写一个测试函数,它接受多个固定装置作为参数。每个灯具都有几个参数。
例如,在test_demo.py中有一个函数test_squared_is_less_than_10
,它以夹具negative_integer
和positive_integer
作为参数,然后检查夹具的平方参数小于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
我希望当我在终端中 运行 pytest 命令时,总共应该执行 6 个测试,即 [-1, -2, -3]
用于 positive_integer
和 [1, 2, 3]
用于negative_integer
.
但是,pytest 似乎执行了一种嵌套循环迭代,因此执行了 9 个测试
即 [(-1, 1), (-1, 2), (-1, 3), (-2, 1), (-2, 2), (-2, 3), (-3, 1), (-3, 2), (-3, 3)]
.
这是我 运行 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
这是不可取的,因为我只想执行 6 个测试而不是 9 个。如果参数数量较多(例如 20 个),pytest 将执行 400 个测试而不是所需的 40 个测试,这是浪费计算时间。
我该如何处理这个问题。
P.S:我想避免写两个单独的测试,比如
test_negative_squared_is_less_than_10(negative_integer)
和 test_positive_squared_is_less_than_10(positive_integer)
您可以通过 @pytest.mark.parametrize
标记应用非笛卡尔参数化。您的代码,已重构:
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