从函数和值字典中进行单元测试
我刚接触Python里的unittests
模块,所以可能有些问题很明显。我有一堆属性想要检查,这些属性存储在一个字典里:
petersen_prop = {
"n_vertex" : 10,
"n_edge" : 15,
...
}
字典里的每个“键”都是一个函数的名字,而对应的值是我希望单元测试验证的目标。现在我用的代码比较冗长:
import unittest
class PetersenGraph(unittest.TestCase):
def setUp(self):
# Create the graph here (not important to the question)
self.args = args
self.adj = adj
def test_n_vertex(self):
self.assertTrue(n_vertex(self.adj,**self.args) ==
petersen_prop["n_vertex"])
def test_n_edge(self):
self.assertTrue(n_edge(self.adj,**self.args) ==
petersen_prop["n_edge"])
# ..... hundreds of similar looking code blocks
unittest.main(verbosity=2)
我感觉这样做有点违反了DRY原则,因为我需要一遍又一遍地复制粘贴同样的代码块。有没有办法可以程序化地添加这些代码块,让单元测试正常工作?简单来说,我希望输入是上面的字典,输出是一个功能相同的单元测试对象。
2 个回答
0
在Python中,想要在一个函数内部获取这个函数的名字,其实是没有直接的功能的。不过,你可以用 test_n_vertex.__name__
这个方式来获取函数的名字,它会返回 'test_n_vertex'
这个字符串。你可以利用一些基本的字符串操作来完成你需要的事情。但是,想要的那种功能是不存在的。
想了解更多信息,可以查看这里: 在函数内部获取函数名(不使用traceback)
1
你可以遍历 petersen_prop
字典里的键,然后根据键的名字调用相应的函数。
def test_n_props(self):
for cur_prop in petersen_prop:
func = globals()[cur_prop]
self.assertTrue(func(self.adj,**self.args) ==
petersen_prop[cur_prop])
或者,如果你不把所有的函数名都导入到测试模块的命名空间里,可以这样做:
def test_n_props(self):
for cur_prop in petersen_prop:
func = getattr(myfuncs, cur_prop)
self.assertTrue(func(self.adj,**self.args) ==
petersen_prop[cur_prop])
你也可以把实际的函数对象存储在 petersen_prop
字典里:
petersen_prop = {
"n_vertex" : (10, n_vertex)
"n_edge" : (15, n_edge)
...
}
def test_n_props(self):
for cur_prop in petersen_prop:
func = petersen_map[cur_prop][1]
self.assertTrue(func(self.adj,**self.args) ==
petersen_prop[cur_prop][0])
编辑:
这里有一种方法可以为字典中的每个项目添加一个独特的测试,使用元类来实现:
class TestMaker(type):
def __new__(cls, clsname, bases, dct):
# Add a method to the class' __dict__ for every key in
# the petersen_prop dict.
for prop in petersen_prop:
dct['test_{}'.format(prop)] = cls.make_test(prop)
return super(TestMaker, cls).__new__(cls, clsname, bases, dct)
@staticmethod
def make_test(prop):
# test_wrap is the method body that will be used for each
# test
def test_wrap(self):
func = getattr(myfuncs, prop)
self.assertTrue(func(self.adj, **self.args) ==
petersen_prop[prop])
return test_wrap
class PetersenGraph(unittest.TestCase):
__metaclass__ = TestMaker
当你运行这个时,每个项目都会得到一个单独的测试用例。例如,在我的测试代码中,每个测试都失败了:
======================================================================
FAIL: test_n_edge (__main__.PetersenGraph)
----------------------------------------------------------------------
Traceback (most recent call last):
File "un.py", line 26, in test_wrap
petersen_prop[prop])
AssertionError: False is not true
======================================================================
FAIL: test_n_vertex (__main__.PetersenGraph)
----------------------------------------------------------------------
Traceback (most recent call last):
File "un.py", line 26, in test_wrap
petersen_prop[prop])
AssertionError: False is not true