pytest-对“乘法表”结果进行参数化所需的最少维护

时间:2018-08-30 16:53:04

标签: python parameters combinations pytest

我想对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标记的支持。但是我可以使用现有工具达到相同的目的吗?请考虑适用于可能无限数量的输入参数的解决方案。

1 个答案:

答案 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框架,该框架基于随机测试的概念运行,从而使功能验证更加广泛。