我想对2个输入值和单个输出值进行参数测试,可以将其与测试乘法表进行比较。为了实现最少的维护,我想出了类似以下内容:
results = [[ 4, 5, 6],
[ 8, 10, 12],
[12, 15, 18]]
@pytest.mark.parametrize("x, ix", [(1, 0), (2, 1), (3, 2)])
@pytest.mark.parametrize("y, iy", [(4, 0), (5, 1), (6, 2)])
def test_multiplication(x, ix, y, iy):
assert x * y == results[ix][iy]
现在,这并不理想,因为如果我想添加新的x
,那么我将不得不添加len(y) + 1 + 1
值,这些值是:3个新的期望值,另外的x
值和索引。理想的情况是仅添加4个值,即没有索引的控制变量。
我也不喜欢results
与测试函数是如何分离的。理想的是:
@pytest.mark.parametrize("x", [1, 2, 3])
@pytest.mark.parametrize("y", [4, 5, 6])
@pytest.mark.result_matrix("result", [
[ 4, 5, 6],
[ 8, 10, 12],
[12, 15, 18],
])
def test_multiplication(x, y, result):
assert x * y == result
我知道我可以自己添加对此类result_matrix
标记的支持。但是我可以使用现有工具达到相同的目的吗?请考虑适用于可能无限数量的输入参数的解决方案。
答案 0 :(得分:0)
我怀疑是否存在真正解决无限数量的参数的方法,但是您可以尝试以下方法:
1)就像@ ev-br建议的那样,在一个parametrize
语句中提供所有函数参数,但是在此之前,您必须在构造函数中为这些参数准备它们。
2)在for
循环中对相同的配置进行相同的操作。它比mark.parametrize
花哨的少,但通常更具可读性。
3)使您的测试参数化或for
循环接受带有参数和结果的字典列表:
# code under test
def foo(x, y):
return x * y
# need a constructor code for these test arguments and results
d0=dict(args=dict(x=2, y=3), result=6)
d1=dict(args=dict(x=5, y=10), result=50)
params = [d0, d1]
# test prototype - goes to pytest
for d in params:
assert foo(**d['args']) == d['result']
我认为这部分与您接受大量争论的概念最接近。
4)您可能还想看看hypothesis框架,该框架基于随机测试的概念运行,从而使功能验证更加广泛。