22

先提问,有兴趣再解释。

在 py.test 的上下文中,我如何从一小组测试功能模板生成大量测试功能?

就像是:

models = [model1,model2,model3]
data_sets = [data1,data2,data3]

def generate_test_learn_parameter_function(model,data):
    def this_test(model,data):
        param = model.learn_parameters(data)
        assert((param - model.param) < 0.1 )
    return this_test

for model,data in zip(models,data_sets):
    # how can py.test can see the results of this function?
    generate_test_learn_parameter_function(model,data)

解释:

我正在编写的代码采用模型结构、一些数据,并学习模型的参数。所以我的单元测试由一堆模型结构和预先生成的数据集组成,然后在每个结构+数据上完成一组大约 5 个机器学习任务。

因此,如果我手动编写代码,我需要为每个任务的每个模型进行一次测试。每次我想出一个新模型时,我都需要复制并粘贴 5 个任务,更改我指向的腌制结构+数据。这对我来说是一种不好的做法。理想情况下,我想要 5 个模板函数来定义我的 5 个任务中的每一个,然后为我指定的结构列表吐出测试函数。

谷歌搜索将我带到 a) 工厂或 b) 闭包,这两者都让我脑筋急转弯,并建议我必须有一种更简单的方法,因为适当的程序员必须经常面对这个问题。那么有吗?


编辑:所以这里是如何解决这个问题!

def pytest_generate_tests(metafunc):
    if "model" in metafunc.funcargnames:
        models = [model1,model2,model3]
        for model in models:
            metafunc.addcall(funcargs=dict(model=model))

def test_awesome(model):
    assert model == "awesome"

这会将test_awesome测试应用于我的模型列表中的每个模型!谢谢@dfichter!

(注意:断言总是通过,顺便说一句)

4

2 回答 2

19

良好的直觉。 用它的钩子py.test完全支持你所说的。pytest_generate_tests()他们在这里解释。

于 2011-02-08T04:05:23.257 回答
8

您也可以使用参数化的固定装置来做到这一点。虽然 hooks 是一个为 Py.test 构建插件的 API,但参数化的固定装置是一种通用的方式来制作输出多个值并为它们生成额外测试用例的固定装置。

插件意味着一些项目范围(或包范围)的功能,而不是测试用例特定的功能,参数化的夹具正是为测试用例参数化某些资源所需要的。

所以你的解决方案可以重写为:

@pytest.fixture(params=[model1, model2, model3])
def model(request):
    return request.param

def test_awesome(model):
    assert model == "awesome"
于 2015-08-11T14:13:29.360 回答