FunctionTestCase方法可以接受参数吗?

时间:2017-08-04 04:47:27

标签: python unit-testing python-unittest

我在Python中使用unittest进行一些测试。我对FunctionTestCase感兴趣。从文档中,这是示例用法:

testcase = unittest.FunctionTestCase(testSomething,
                                     setUp=makeSomethingDB,
                                     tearDown=deleteSomethingDB)

testSomething定义为

def testSomething():
    something = makeSomething()
    assert something.name is not None
    # ...

但是,我有兴趣将参数传递给testSomething(),如下所示。

  def testSomething(input):
        something = makeSomething(input)
        assert something.name is not None
        # ...

当我运行它时,如上所述构建它:

runner= unittest.TextTestRunner()
runner.run(testcase)

我得到了

    ERROR: unittest.case.FunctionTestCase (test_meth4)
----------------------------------------------------------------------
TypeError: testSomething() missing 1 required positional argument: 'input'

----------------------------------------------------------------------
Ran 1 tests in 0.007s

有没有办法传递参数,还是需要使用像闭包/外部函数这样的东西?感谢

2 个答案:

答案 0 :(得分:0)

看起来你可以将参数传递给正在测试的函数。在Python 2和3中,FunctionTestCase.runTest()只包含一行:self._testFunc(),没有提供传递参数的规定。您可以将FunctionTestCase子类化并向其__init__()添加参数,然后让runTest()将它们传递给正在测试的函数:

import unittest

def my_func(arg1, arg2=None):
    print('arg1 is', arg1)
    print('arg2 is', arg2)

class MyFunctionTestCase(unittest.FunctionTestCase):
    def __init__(self, testFunc, setUp=None, tearDown=None,
                 description=None, args=(), kwargs={}):
        super(MyFunctionTestCase, self).__init__(testFunc, setUp=setUp,
                                                 tearDown=tearDown,
                                                 description=description)
        self.args = args
        self.kwargs = kwargs

    def runTest(self):
        self._testFunc(*self.args, **self.kwargs)

my_test = unittest.FunctionTestCase(my_func)
my_subclassed_test = MyFunctionTestCase(my_func, args=(42,), kwargs={'arg2': 24})

runner = unittest.TextTestRunner()
runner.run(my_test)
runner.run(my_subclassed_test)

我建议您在https://bugs.python.org申请此功能和/或更多文档。这似乎是一个很大的差距,实际上没有FunctionTestCase的官方文档。

答案 1 :(得分:0)

如前所述,不可能使用 unittest.FunctionTestCase() 为您的测试函数提供参数。但是,您可以使用 functools.partial() 创建一个包装函数,该函数使用附加参数调用原始函数。

以您的原始示例为例,您可以执行以下操作:

wrapped_func = functools.partial(testSomething, input)
wrapped_func()  # this is now equivalent to testSomething(input)

请注意,input 也是 Python 中内置函数的名称,因此我建议您为变量使用另一个名称。

基于另一个答案的完整工作示例(为了更容易比较)是这样的:

import functools
import unittest

def my_func(arg1, arg2=None):
    print('arg1 is', arg1)
    print('arg2 is', arg2)

my_wrapped_func = functools.partial(my_func, 42, arg2=24)
functools.update_wrapper(my_wrapped_func, my_func)
my_wrapped_test = unittest.FunctionTestCase(my_wrapped_func)

runner = unittest.TextTestRunner()
runner.run(my_wrapped_test)

带有 update_wrapper() 的行是必要的,以使包装的函数看起来更像原始函数,这是 unittest 框架在失败时打印函数名称所必需的。