编写自编写测试方法的pythonic方法

时间:2013-12-11 09:44:59

标签: python unit-testing

我定义了以下测试类。它使用exec,我通常不喜欢它。

class FubarTest(unittest.TestCase):
    lst = [(True, True),
           (False, False)]
    for t in lst:
        function = """def test_{}_is_{}(self):
        self.assertTrue({} is {})
        """.format(t[0], t[1], t[0], t[1])
        exec function

当我运行它时(通过py.test,但这不重要),我明白了:

============================= test session starts ==============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.4 -- /usr/bin/python
plugins: capturelog, cov, twisted, xdist

model/test/test_hframe5.py <- <string>:1: HFrame5Test.test_False_is_False PASSED
model/test/test_hframe5.py <- <string>:1: HFrame5Test.test_True_is_True PASSED
=========================== 2 passed in 0.49 seconds ===========================

因此,测试会自动创建并具有合理的名称,因此如果出现问题,您可以通过方法的名称知道失败的原因。

显然,这是我想要做的简化示例。我有很多测试看起来像“做X,检查Y是真,Z是假”,可以用上面的方法轻松编码。我可以写三打复制和粘贴的方法,但这感觉不对 - 打破DRY。

是否有更多pythonic方式编写此代码?

4 个答案:

答案 0 :(得分:1)

我通常会在更多测试方面犯错,而不是更少测试,真的无论如何完成。你可能没事。

答案 1 :(得分:1)

您需要参数化测试。例如,使用parameterizedtestcase

from parameterizedtestcase import ParameterizedTestCase

class MyTests(ParameterizedTestCase):
    @ParameterizedTestCase.parameterize(
        ("value", "expected"),
        [
            (True, True),
            (False, False),
        ]
    )
    def test_identical(self, value, expected):
        self.assertTrue(value is expected)

使用py.test's parametrization framework

import pytest

@pytest.mark.parametrize(
    ("value", "expected"),
    [
        (True, True),
        (False, False),
    ]
)
def test_identical(value, expected):
    assert value is expected

答案 2 :(得分:1)

您几乎肯定不需要使用exec。只需使用'setattr'为类添加合适的函数,并使用嵌套的范围来绑定测试值。例如,我认为这应该有效:

class FubarTest(unittest.TestCase):
    pass

def createTest(cls, arg1, arg2):
    def test(self):
        self.assertTrue(arg1 is arg2)
    testname = "test_{}_is_{}".format(arg1, arg2)
    setattr(cls, testname, test)

def createTests():
    lst = [(True, True),
        (False, False)]
    for a,b in lst:
        createTest(FubarTest, a, b)

createTests()

答案 3 :(得分:1)

如果你使用鼻子,你可以使用test generator

class FubarTest(object):

    def check_is(self, a, b):
        assert {} is {}

    def test_is(self):
        lst = [(True, True), (False, False)]
        for a, b in lst:
            self.check_is(a, b)