如何在 python3 中的慢速测试中尽早失败(例如设置超时)(最好使用鼻子)

How to fail early (e.g. set a timeout) on slow tests in python3 (preferably using nose)

下面的代码重现了我的情况:

from nose.tools import timed
from time import sleep


class Test():
    @timed(1)
    def test_slow_function(self):
        duration = 5
        sleep(duration)
        pass

运行 测试(例如 nosetests test.py:Test -s),我预计 1 秒后会出现失败结果。 令我惊讶的是,直到测试完成(在本例中为 5 秒后)它才会失败。哪怕1秒之后的任何结果都已经是失败了。我得到:

...
    raise TimeExpired("Time limit (%s) exceeded" % limit)
nose.tools.nontrivial.TimeExpired: Time limit (1) exceeded

----------------------------------------------------------------------
Ran 1 test in 5.006s

FAILED (failures=1)

我想避免测试套件永远不会结束的可能性(例如,在某些情况下会出现无限循环)。哪种方法比较好?

@timed 装饰器无法停止装饰函数的执行。它所做的只是将实际执行时间与预期执行时间进行比较,如果超出则引发失败。

基本上,要监视某些进程并在某些情况下停止它(如果太长,在您的示例中),您需要并行的另一个进程,它实际上会进行监视。实现此目的的简单且有点老套的方法是使用 nose 的并行测试执行,如下所示:

$ nosetests test.py:Test -s --processes 2 --process-timeout 1
E
======================================================================
ERROR: timesout_nose.Test.test_slow_function
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/test.py", line 9, in test_slow_function
    sleep(duration)
  File "/venv/lib/python3.6/site-packages/nose/plugins/multiprocess.py", line 276, in signalhandler
    raise TimedOutException()
nose.plugins.multiprocess.TimedOutException: 'test.Test.test_slow_function'

----------------------------------------------------------------------
Ran 1 test in 1.230s

FAILED (errors=1)

您可以在这里阅读更多内容: http://nose.readthedocs.io/en/latest/plugins/multiprocess.html

但是,您无法像使用装饰器那样设置简单的时间限制。但是你仍然可以用它来捕获无限循环。