如何将复杂的类成员传递给pytest parametrize装饰器

时间:2018-02-14 09:48:09

标签: python class pytest

我需要将类成员作为参数传递给pytest.mark.parametrize。 以下代码不起作用(我使用了简单的成员字符串,但在我的情况下,它们是复杂的并构造的):

import pytest
class TestSmth(object):
     def setup_class(cls):
         cls.a = "a"
         cls.b = "b"
         cls.c = "c"

     @pytest.mark.parametrize("test_input,expected", [
     (self.a, "a"),
     (self.b, "b"),
     (self.c, "c")
     ])
     def test_members(test_input, expected):
         assert test_input == expected

有可能实现这样的结果吗? 或类似的东西?

2 个答案:

答案 0 :(得分:1)

此代码不起作用,因为Python装饰器don't work that way。它与测试参数中的实际数据无关。如果你是编写装饰器的人,你可以solve it by manually passing the instance,但这取决于装饰者本身做正确的事。

目前,pytest修饰器只是存储要验证的测试数据 - 因此您需要提供在运行desugared代码时可访问的数据,如下所示:

o = TestSmth()
o.setup_class()

@pytest.mark.parametrize("test_input,expected", [
(o.a, "a"),
(o.b, "b"),
(o.c, "c")
])
def test_members(test_input, expected):
    assert test_input == expected

我认为传递给这些函数的数据类型没有任何固有的限制。如果您仍然发现限制太多,则pytest对自定义参数化方案有substantial support。如果没有实际使用的细节(而不是模拟示例),很难说出最适合问题的方法。

答案 1 :(得分:0)

在pytest docs中找到解决方案 - > “通过每类配置参数化测试方法¶”

#!/usr/bin/env python

import pytest


def pytest_generate_tests(metafunc):
    # called once per each test function
    funcarglist = metafunc.cls.params[metafunc.function.__name__]
    argnames = sorted(funcarglist[0])
    metafunc.parametrize(argnames, [[funcargs[name] for name in argnames]
            for funcargs in funcarglist])

class Complex(object):
    def __init__(self):
        self.a = "a"

class TestBase(object):
    A = Complex()
    params = {
        'test_a' : [dict (test_input=A)]
    }

    def test_a(self, test_input):
        assert test_input.a == "a"

这很丑陋,但却符合它的目的。