Python 3 unittest:可以追加新的 test_* 方法吗?
我正在使用Python 3.4.1和unittest模块来验证另一个软件。
这个软件需要运行,然后它的输出结果必须通过Python脚本进行解析,以便进行验证。输出文件是一个XML文件,里面包含了不确定数量的元素。
目前,我一直在使用subTest()
为每个XML元素生成一个子测试。这并不是我想要的结果。
我希望为XML文件中的每个元素创建一个test_*方法。问题是我事先不知道会有多少个元素,所以我需要一种方法来自动添加新的test_*方法到unittest中。我想到了一个setUpClass()方法,它可以调用外部软件来生成XML,并建立一个要运行的test*方法的更新列表。
但是我觉得这些方法是在任何东西执行之前就被添加到unittest的运行方法列表中的,所以当我到达添加新方法的那一步时(例如在setUpClass()
中使用setattr()
),列表已经建立好了,而新方法却从未被运行过……
在unittest中动态改变要运行的方法列表是可能的吗?
谢谢!
2 个回答
我想出了这个方法。尝试了一下@big_gie提交的代码。这样一来,setUp和tearDown也会按照单元测试的规则运行。
import unittest
def generator(test_class, a, b):
def test(self):
self.assertEqual(a, b)
return test
def add_test_methods(test_class):
test_list = [[2,3, 'one'], [5,5, 'two'], [0,0, 'three']]
for case in test_list:
test = generator(test_class, case[0], case[1])
setattr(test_class, "test_%s" % case[2], test)
class TestIO(unittest.TestCase):
def setUp(self):
print 'Setup'
pass
def tearDown(self):
print 'TearDown'
pass
add_test_methods(TestIO)
if __name__ == '__main__':
unittest.main(verbosity=1)
结果:
>>>
Setup
FTearDown
Setup
TearDown
.Setup
TearDown
.
======================================================================
FAIL: test_one (__main__.TestIO)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:/inchowar/Desktop/PyTrash/test_auto_3.py", line 5, in test
self.assertEqual(a, b)
AssertionError: 2 != 3
----------------------------------------------------------------------
Ran 3 tests in 0.019s
FAILED (failures=1)
这是我想到的一种变体:
import unittest
class MyClass:
def setup(self):
# run external software
def parse_xml(self):
# parse the xml file
def generator(self, test_class, a, b):
def test(self):
self.assertEqual(a, b)
return test
def add_test_methods(self, test_class):
for i in range(len(self.all_status)):
test = self.generator(test_class, self.all_status[i], STATUS_SUCCESS)
setattr(test_class, "test_uid_%d" % i, test)
class TestIO(unittest.TestCase):
pass
mb = MyClass()
mb.setup()
mb.parse_xml()
mb.add_test_methods(TestIO)
if __name__ == '__main__':
unittest.main()
关键在于在任何类之外生成和解析XML文件,然后使用 setatt()
将生成的方法添加到类中。不过,这种方法的问题是它在测试套件之外运行代码,我本来不想这样做。所以如果那里出错,就会导致整个测试套件崩溃(因为 unittest
不会捕捉到这个错误...)
也许我可以把XML生成移到一个单独的测试类里?
有没有更好的建议?