如果你真的想要多个 unitttest 那么你需要多个方法。获得它的唯一方法是通过某种代码生成。您可以通过元类来做到这一点,或者在定义之后调整类,包括(如果您使用的是 Python 2.6)通过类装饰器。
这是一个寻找特殊的'multitest'和'multitest_values'成员并使用它们动态构建测试方法的解决方案。不优雅,但它大致可以满足您的要求:
import unittest
import inspect
class SomeValue(object):
def __eq__(self, other):
return other in [1, 3, 4]
class ExampleTestCase(unittest.TestCase):
somevalue = SomeValue()
multitest_values = [1, 2, 3, 4]
def multitest(self, n):
self.assertEqual(self.somevalue, n)
multitest_gt_values = "ABCDEF"
def multitest_gt(self, c):
self.assertTrue(c > "B", c)
def add_test_cases(cls):
values = {}
functions = {}
# Find all the 'multitest*' functions and
# matching list of test values.
for key, value in inspect.getmembers(cls):
if key.startswith("multitest"):
if key.endswith("_values"):
values[key[:-7]] = value
else:
functions[key] = value
# Put them together to make a list of new test functions.
# One test function for each value
for key in functions:
if key in values:
function = functions[key]
for i, value in enumerate(values[key]):
def test_function(self, function=function, value=value):
function(self, value)
name ="test%s_%d" % (key[9:], i+1)
test_function.__name__ = name
setattr(cls, name, test_function)
add_test_cases(ExampleTestCase)
if __name__ == "__main__":
unittest.main()
这是我运行它时的输出
% python stackoverflow.py
.F..FF....
======================================================================
FAIL: test_2 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 13, in multitest
self.assertEqual(self.somevalue, n)
AssertionError: <__main__.SomeValue object at 0xd9870> != 2
======================================================================
FAIL: test_gt_1 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 17, in multitest_gt
self.assertTrue(c > "B", c)
AssertionError: A
======================================================================
FAIL: test_gt_2 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 17, in multitest_gt
self.assertTrue(c > "B", c)
AssertionError: B
----------------------------------------------------------------------
Ran 10 tests in 0.001s
FAILED (failures=3)
您可以立即看到代码生成中出现的一些问题。“test_gt_1”从何而来?我可以将名称更改为更长的“test_multitest_gt_1”,但是哪个测试是 1?最好从 _0 而不是 _1 开始,也许在您的情况下,您知道这些值可以用作 Python 函数名称。
我不喜欢这种方法。我研究过自动生成测试方法的代码库(在一种情况下使用元类),发现它更难理解而不是有用。当测试失败时,很难找出失败案例的来源,也很难坚持调试代码来探查失败的原因。
(我在这里编写的示例中的调试失败并不像我必须使用的特定元类方法那么难。)