Jur*_*ury 19 python unit-testing timeout
我正在使用python
框架unittest
.是否可以通过框架的能力指定测试超时?如果不是,是否可以timeout
为所有测试和某些单独的测试优雅地指定每个测试的私有值?
我想global timeout
为所有测试定义一个(默认情况下它们将使用它)和一些可能需要很长时间的测试的超时.
Lav*_*Lav 22
据我所知unittest
,不包含对测试超时的任何支持.
您可以timeout-decorator
从PyPI 尝试库.在各个测试中应用装饰器,如果它们花费太长时间使它们终止:
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 ...
Run Code Online (Sandbox Code Playgroud)
要创建全局超时,您可以替换呼叫
unittest.main()
Run Code Online (Sandbox Code Playgroud)
同
timeout_decorator.timeout(GLOBAL_TIMEOUT)(unittest.main)()
Run Code Online (Sandbox Code Playgroud)
我根据这个答案unittest
使用上下文管理器(with
keyowrd)构建了一个超时解决方案。
这种方法也使用signal
,所以它可能只在 *nix 系统上有效(我只在我的 Ubuntu 16.04 环境中运行它)。
TestTimeout
异常:import signal
...
class TestTimeout(Exception):
pass
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
with test_timeout()
在单元测试中嵌入块:def test_foo(self):
with test_timeout(5): # test has 5 seconds to complete
... foo unit test code ...
Run Code Online (Sandbox Code Playgroud)
使用这种方法,超时的测试将由于异常而导致错误raise TestTimeout
。
或者,您可以将with test_timeout()
块包装在一个try: except TestTimeout:
块中,并以更大的粒度处理异常(例如跳过测试而不是错误)。