Python 3 unittest:可以追加新的 test_* 方法吗?

1 投票
2 回答
763 浏览
提问于 2025-04-18 18:46

我正在使用Python 3.4.1和unittest模块来验证另一个软件。

这个软件需要运行,然后它的输出结果必须通过Python脚本进行解析,以便进行验证。输出文件是一个XML文件,里面包含了不确定数量的元素。

目前,我一直在使用subTest()为每个XML元素生成一个子测试。这并不是我想要的结果。

我希望为XML文件中的每个元素创建一个test_*方法。问题是我事先不知道会有多少个元素,所以我需要一种方法来自动添加新的test_*方法到unittest中。我想到了一个setUpClass()方法,它可以调用外部软件来生成XML,并建立一个要运行的test*方法的更新列表。

但是我觉得这些方法是在任何东西执行之前就被添加到unittest的运行方法列表中的,所以当我到达添加新方法的那一步时(例如在setUpClass()中使用setattr()),列表已经建立好了,而新方法却从未被运行过……

在unittest中动态改变要运行的方法列表是可能的吗?

谢谢!

2 个回答

0

我想出了这个方法。尝试了一下@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)
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生成移到一个单独的测试类里?

有没有更好的建议?

撰写回答