如何在公共函数中提供额外的参数以用于测试目的?

时间:2014-08-29 14:00:03

标签: python

我有一个公共职能fun(a, b)。现在,出于测试目的,我希望fun再增加一个参数test_argument

接受这种方式的方法是什么? 我的想法:

def fun(a, b, test_argument=None):
    ...

但它并不漂亮,因为每个使用此函数的人都会看到test_argument参数,并且至少需要注释。

def fun(a, b, **kwargs):
    ...
    test_argument = kwargs.get('test_argument', None)

现在有人可能想知道**kwargs是什么。

编辑:我想要这个,因为fun的结构如下:

def fun(a, b):
    do_locally(a, b)
    if condition(a, b):
        do_locally1(a, b)
        do_remotely_after_one_minute(a, b)
    else:
        do_locally2(a, b)
        do_remotely_after_two_minutes(a, b)

我想在调用a之后但在远程执行开始之前测试bfun(a, b)的状态。但是,在项目中,远程执行的代码在测试中内联(0%有机会更改此行为)。所以我考虑传递一个额外的论点:

def fun(a, b, test=False):
    do_locally(a, b)
    if condition(a, b):
        do_locally1(a, b)
        if not test:
            do_remotely_after_one_minute(a, b)
    else:
        do_locally2(a, b)
        if not test:
            do_remotely_after_two_minutes(a, b)

3 个答案:

答案 0 :(得分:2)

你的do_remotely_after_*函数都只是全局名称;它们可以在测试期间暂时更换:

import module_under_test

def test_fun():
    # patch remote methods with noops
    draom = module_under_test.do_remotely_after_one_minute
    module_under_test.do_remotely_after_one_minute = lambda *args: pass
    dratm = module_under_test.do_remotely_after_two_minutes
    module_under_test.do_remotely_after_two_minutes = lambda *args: pass

    module_under_test.fun(a, b)

    # restore remote methods
    module_under_test.do_remotely_after_one_minute = draom
    module_under_test.do_remotely_after_two_minutes = dratw

您可以使用上下文管理器来处理修补和恢复,但最好的方法是使用mock library为您处理:

@mock.patch('module_under_test.do_remotely_after_one_minute')
@mock.patch('module_under_test.do_remotely_after_two_minutes')
def test_fun(mock_dratm, mock_draom):
    module_under_test.fun(a, b)

并且也可以访问模拟,因此您可以断言是否已正确调用它们。

答案 1 :(得分:1)

你应该使用mock库。它是为这个员工准备的:

>>> def do_loc(a,b):
...   return "IN do_loc %s %s" % (a, b)
... 
>>> def do_remte(a,b):
...   return "IN do_remte %s %s" % (a, b)
... 
>>> def foo(a,b):
...   print do_loc(a,b)
...   print do_remte(a,b)
... 
>>> with mock.patch('__main__.do_remte') as mock_remte:
...   mock_remte.return_value = "MY MOCK"
...   foo('A', 'B')
... 
IN do_loc A B
MY MOCK
>>> 

答案 2 :(得分:1)

这与Martijn Pieters的答案几乎相同,但是使用了mock库。

import module_under_test
try:
    # Standard library as of Python 3.4
    import unittest.mock as mock
except ImportError:
    # 3rd-party installation
    import mock

def test_fun():
    # patch remote methods with noops
    with mock.patch.multiple('module_under_test',
                             do_remotely_after_one_minute=mock.DEFAULT,
                             do_remotely_after_two_minute=mock.DEFAULT) as values:
        fun(a, b)
        # If desired, you can use values['do_remotely_after_one_minute'] to query
        # the mocked function as to whether or not it was called, what arguments
        # it was called with, etc.