【发布时间】:2016-04-17 01:19:53
【问题描述】:
我正在使用python 框架unittest。是否可以通过框架的能力指定测试超时?如果不是,是否可以为所有测试优雅地指定 timeout 并为某些单独的测试为每个测试指定一个私有值?
我想为所有测试定义一个global timeout(默认情况下会使用它),并为一些可能需要很长时间的测试定义一个超时。
【问题讨论】:
标签: python unit-testing timeout
我正在使用python 框架unittest。是否可以通过框架的能力指定测试超时?如果不是,是否可以为所有测试优雅地指定 timeout 并为某些单独的测试为每个测试指定一个私有值?
我想为所有测试定义一个global timeout(默认情况下会使用它),并为一些可能需要很长时间的测试定义一个超时。
【问题讨论】:
标签: python unit-testing timeout
我使用上下文管理器(with keyowrd)、based on this answer 构建了一个 unittest 超时解决方案。
这种方法也使用signal,所以它可能只在 *nix 系统上有效(我只在我的 Ubuntu 16.04 环境中运行过)。
TestTimeout异常:import signal
...
class TestTimeout(Exception):
pass
test_timeout,它将处理with 块:class test_timeout:
def __init__(self, seconds, error_message=None):
if error_message is None:
error_message = 'test timed out after {}s.'.format(seconds)
self.seconds = seconds
self.error_message = error_message
def handle_timeout(self, signum, frame):
raise TestTimeout(self.error_message)
def __enter__(self):
signal.signal(signal.SIGALRM, self.handle_timeout)
signal.alarm(self.seconds)
def __exit__(self, exc_type, exc_val, exc_tb):
signal.alarm(0)
with test_timeout() 块:def test_foo(self):
with test_timeout(5): # test has 5 seconds to complete
... foo unit test code ...
使用这种方法,超时的测试将由于raise TestTimeout 异常而导致错误。
或者,您可以将 with test_timeout() 块包装在 try: except TestTimeout: 块中,并以更精细的方式处理异常(例如,跳过测试而不是错误)。
【讨论】:
据我所知unittest 不包含对测试超时的任何支持。
您可以尝试 PyPI 中的 timeout-decorator 库。将装饰器应用于单个测试以使它们在耗时过长时终止:
import timeout_decorator
class TestCaseWithTimeouts(unittest.TestCase):
# ... whatever ...
@timeout_decorator.timeout(LOCAL_TIMEOUT)
def test_that_can_take_too_long(self):
sleep(float('inf'))
# ... whatever else ...
要创建全局超时,可以替换调用
unittest.main()
与
timeout_decorator.timeout(GLOBAL_TIMEOUT)(unittest.main)()
【讨论】:
unittest.main(),但我希望我的情况可以采用decorator。但是我的测试不是在单线程中进行的......
timeout-decorator reference 中的“多线程”部分 - 您只需要在多线程环境中使用timeout_decorator.timeout(TIMEOUT, use_signals=False)。
use_signals=False 对我不起作用,但它看起来工作的信号。正如我发现的那样,这个模块使钩子直接调用_Timeout.__call__ 而不是 testmethod。问题实际上是 testmethod 的self 被_Timeout 的self 丢失(替换)。调用时,testmethod 没有任何 self 并且它失败了。我不知道发生了什么以及如何解决它。全局超时的技巧也不起作用。
@timeout_decorator.timeout(TIMEOUT, timeout_exception=StopIteration)。您需要将此装饰器放在所有潜在的堆叠测试中。就我而言,它是在与 async/websocket 相关的测试中