繁体   English   中英

Python:在单元测试期间如何覆盖复杂的函数?

[英]Python: how can I override a complicated function during unittest?

我正在使用Python的unittest模块来测试正在编写的脚本。

该脚本包含如下循环:

// my_script.py

def my_loopy_function():
    aggregate_value = 0
    for x in range(10):
        aggregate_value = aggregate_value + complicated_function(x)
    return aggregate_value

def complicated_function(x):
    a = do()
    b = something()
    c = complicated()
    return a + b + c

我使用没有问题unittest来测试complicated_function 不过,我想测试my_loopy_function通过重写complicated_function

我试图修改我的脚本,以便my_loopy_function需要complicated_function作为可选参数,这样我可以从测试的简单版本通过:

// my_modified_script.py

def my_loopy_function(action_function=None):
    if action_function is not None:
        complicated_function = action_function
    aggregate_value = 0
    for x in range(10):
        aggregate_value = aggregate_value + complicated_function(x)
    return aggregate_value

def complicated_function(x):
    a = do()
    b = something()
    c = complicated()
    return a + b + c

// test_my_script.py

from myscript import my_loopy_function

class TestMyScript(unittest.TestCase):
    test_loopy_function(self):
        def simple_function():
            return 1
    self.assertEqual(10, my_loopy_function(action_function=simple_function))

它没有按我希望的那样工作,是否有关于如何进行此操作的建议?

不要试图重写complicated_functionaction_function ,只需使用complicated_function作为默认action_function

def my_loopy_function(action_function=complicated_function):
    aggregate_value = 0
    for x in range(10):
        aggregate_value = aggregate_value + action_function(x)
    return aggregate_value

最后,我使用了Python的mock ,它使我可以覆盖complicated_function而不必以任何方式调整原始代码。

这里是原始脚本,并注意complicated_function不传递给my_loopy_function作为“ action_function ”参数(这是我在我的早期解决方案试过):

// my_script.py

def my_loopy_function():
    aggregate_value = 0
    for x in range(10):
        aggregate_value = aggregate_value + complicated_function(x)
    return aggregate_value

def complicated_function(x):
    a = do()
    b = something()
    c = complicated()
    return a + b + c

这是我用来测试的脚本:

// test_my_script.py

import unittest
import mock
from my_script import my_loopy_function

class TestMyModule(unittest.TestCase):
    @mock.patch('my_script.complicated_function')
    def test_1(self, mocked):
        mocked.return_value = 1
        self.assertEqual(10, my_loopy_function())

就像我想要的那样工作:

  1. 我可以用更简单的自身版本代替功能,以便更轻松地进行测试,
  2. 我不需要以任何方式更改我的原始代码(例如,我尝试过-通过传递函数指针有效地进行了更改), mock模块使我可以对内部对象进行后期编码访问。

感谢奥斯丁提出的使用mock建议。 顺便说一句,我正在使用Python 2.7,因此使用了PyPI的pip -installable mock

在您的代码中,您不应该能够像这样覆盖complicated_function 如果尝试,我会UnboundLocalError: local variable 'complicated_function' referenced before assignment得到UnboundLocalError: local variable 'complicated_function' referenced before assignment

但是,也许是这样的问题:在您的实际代码中,您是以其他方式(例如,作为模块的成员)引用了complicated_function吗? 然后通过在测试中覆盖它,就覆盖了实际的complicated_function ,因此您将无法在其他测试中使用它。

正确的方法是用全局变量覆盖局部变量,如下所示:

def my_loopy_function(action_function=None):
  if action_function is None:
    action_function = complicated_function
  aggregate_value = 0
    for x in range(10):
      # Use action_function here instead of complicated_function
      aggregate_value = aggregate_value + action_function(x)
    return aggregate_value

暂无
暂无

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

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