在pytest中断言没有无限循环

时间:2018-04-23 10:19:28

标签: python infinite-loop pytest

我有一个不应该挂起的功能。具体来说,它会检测导致挂起的条件并引发错误。简化,我的功能类似于这个:

def chew_repeated_leading_characters(string: str, leader: str):
    if len(leader) == 0:
        # Without this, will hang on empty string
        raise ValueError('leader cannot be empty')

    while True:
        if string.startswith(leader):
            string = string[len(leader):]
        else:
            break

    return string

我想在pytest中编写单元测试以确保此行为。我知道如何断言测试应该引发异常。但是,在这种情况下,如果测试失败,它实际上不会失败;整个测试设备都挂了。

如何在无限循环中生成测试失败?

3 个答案:

答案 0 :(得分:2)

这种断言不存在。 “无无限循环”断言将成为values的解决方案,事实证明它没有。

您应该检查是否发生在之后发生了一个事件,如果发生了,则会失败。如果您的函数在该raise子句之后使用副作用,那么最好检查该副作用,而不是向测试添加任意超时。

例如,这种方法:

side_effect()

可以通过模拟string来测试,并使其在通话时触发失败。

超时应该被用作最后的解决方案。

编辑:关于你的代码,很容易做到没有超时 - 传递一个模拟startswith(),在调用from mock import Mock ... string_mock = Mock() string.startswith.side_effect = AssertionError('This will hang.') leader_mock = Mock() leader.__len__ = lambda self: 0 chew_repeated_leading_characters(string_mock, leader_mock) 时触发失败:

{{1}}

答案 1 :(得分:1)

在数学上不可能断言这一点。请参阅the Halting Problem

然而,你可以做的是设置一个闹钟,在经过一段时间后停止运行。如果测试仍在运行,则表示失败。

无需查看任何代码,很难提出更明确的建议。

答案 2 :(得分:1)

虽然上述答案是正确的,但在一般意义上不可能这样做,但您可以使用类似https://pypi.org/project/pytest-timeout/的内容来实现解决方案。