【问题标题】:override python function-local variable in unittest覆盖单元测试中的python函数局部变量
【发布时间】:2015-04-25 14:51:39
【问题描述】:

我在 python (2.7) 中有一个方法可以执行 foo,如果 foo 不起作用,则在 5 分钟后放弃。

def keep_trying(self):
    timeout = 300  #empirically derived, appropriate timeout
    end_time = time.time() + timeout
    while (time.time() < end_time):
        result = self.foo()
        if (result == 'success'):
            break
        time.sleep(2)
    else:
        raise MyException('useful msg here')

我知道 foo() 的一些可能结果,所以我使用 mock 来伪造这些返回值。问题是,我不希望测试在看到异常之前运行 5 分钟。

有没有办法覆盖本地超时值?我希望这只是几秒钟,以便我可以看到循环尝试几次,然后放弃并加注。

以下不起作用:

@patch.object(myClass.keep_trying, 'timeout')
@patch.object(myClass, 'foo')
def test_keep_trying(self, mock_foo, mock_timeout):
    mock_foo.return_value = 'failed'
    mock_timeout.return_value = 10 # raises AttributeError
    mock_timeout = 10 # raises AttributeError
    ...

【问题讨论】:

    标签: python mocking unit-testing


    【解决方案1】:

    您不能模拟函数的局部变量。为了使您的代码更易于测试,请将其更改为,例如:

    def keep_trying(self, timeout=300):
        end_time = time.time() + timeout
        # etc, as above
    

    所以测试以更短的超时时间运行它变得微不足道!

    【讨论】:

    • 原始函数是已发布 API 的一部分,因此我不想更改签名,也不希望用户有权调整该超时。
    • Python 作为君子协议和某些约定工作——如果你让参数有一个前导下划线——你的用户会知道不应该使用这个参数——任何体面的文档系统都可以让你无论如何都要忽略私有参数、方法、字段等,所以只有非常坚定的用户才会首先找到参数。
    【解决方案2】:

    与其尝试模拟timeout 的值,不如模拟time.time() 的返回值。

    例如

    @patch.object(time, 'time')
    def test_keep_trying(self, mock_time):
        mock_time.side_effect = iter([100, 200, 300, 400, 500, 600, 700, 800])
        ...
    

    现在第一次调用time.time(),你会得到100的值,所以在你的while循环几圈后它应该超时。您还可以模拟 time.sleep 并计算它被调用的次数,以确保该部分代码正常工作。


    另一种方法(与上述方法不完全正交)是允许用户将可选的超时关键字传递给函数:

    def keep_trying(self, timeout=300):
        ...
    

    这允许您在测试中指定您想要的任何超时时间(以及在以后不想等待 5 分钟的代码中;-)。

    【讨论】:

    • 实际上,我使用@patch.object(myClass.time, 'time') 将 mock.side_effect 保留在该模块的本地。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多