我定义了以下测试类。它使用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方式编写此代码?
答案 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)