简体   繁体   English

从功能和值的字典中进行单元测试

[英]Unittest from a dictionary of functions and values

I'm new to the unittests module in Python, so the answer may be obvious. 我是Python中的unittests模块的新手,所以答案可能很明显。 I have a bunch of properties I'd like to check that I've stored in a dictionary: 我想检查一堆存储在字典中的属性:

petersen_prop = {
    "n_vertex" : 10,
    "n_edge"   : 15,
    ...
}

Each "key" is the name of a function and the value is the target I'd like unittests to verify. 每个“键”都是函数的名称,值是我希望单元测试验证的目标。 What works is the rather verbose code: 起作用的是相当冗长的代码:

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)

It seems like I'm violating DRY, I have to copy and paste the same code block over and over. 好像我违反了DRY,我必须一遍又一遍地复制并粘贴相同的代码块。 Is there a way to programmatically add these code blocks so unit tests will work as expected? 有没有办法以编程方式添加这些代码块,以便单元测试可以按预期工作? To be clear, I'd like the input to be the dictionary above, and the output to be a unittest object that works identically. 明确地说,我希望输入是上面的字典,而输出是工作相同的unittest对象。

You can iterate over the keys in the petersen_prop dictionary, and call the correct function based on the key name. 您可以遍历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])

Or, if you don't import all the function names into the test module's namespace, like this: 或者,如果不将所有函数名称都导入到测试模块的名称空间中,则如下所示:

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])

You could also store the actual function object in the petersen_prop dict: 您还可以将实际的函数对象存储在petersen_prop dict中:

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])

Edit: 编辑:

Here's a way to add a unique test for each item in the dict, using a metaclass: 这是一种使用元类为字典中的每个项目添加唯一测试的方法:

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

When you run this, you'll get a separate test case for each item. 运行此命令时,您将为每个项目获得一个单独的测试用例。 For example, in my test code I had each test fail: 例如,在我的测试代码中,每个测试都失败了:

======================================================================
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

Python doesn't have the functionality to get the name of the function from within the function. Python没有从函数内部获取函数名称的功能。 What you can do is test_n_vertex.__name__ and it will give you 'test_n_vertex' as a string. 您可以做的是test_n_vertex.__name__ ,它将为您提供'test_n_vertex'作为字符串。 You can use basic string functions to do what you need to do. 您可以使用基本的字符串函数来执行所需的操作。 But the exact functionality you're expecting doesn't exist. 但是,您所期望的确切功能并不存在。

See here for more info Determine function name from within that function (without using traceback) 有关更多信息,请参见此处。 从该函数中确定函数名称(不使用回溯)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM