如何为python unittest指定测试超时?

时间:2016-01-12 12:15:41

标签: python unit-testing timeout

我正在使用python框架unittest。是否有可能通过框架的能力指定测试超时?如果不是,是否可以优雅地为所有测试指定timeout,为某些单独的测试指定每个测试的私有值?
我想为所有测试定义一个global timeout(默认情况下它们将使用它),并且可能需要很长时间才能进行一些测试的超时。

2 个答案:

答案 0 :(得分:18)

据我所知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)()

答案 1 :(得分:4)

我使用unittest keyowrd based on this answer构建了with超时解决方案。

此方法也使用signal,因此它可能仅在* nix系统上有效(我只在我的Ubuntu 16.04环境中运行它。)

  1. 导入信号,添加TestTimeout例外:
  2. import signal
    
    ...
    
    class TestTimeout(Exception):
        pass
    
    1. 定义类test_timeout,它将处理with块:
    2. 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)
      
      1. 在单元测试中嵌入with test_timeout()块:
      2. def test_foo(self):
          with test_timeout(5):  # test has 5 seconds to complete
            ... foo unit test code ...
        

        使用这种方法,由于引发TestTimeout异常,超时测试将导致错误。

        或者,您可以将with test_timeout()块包装在try: except TestTimeout:块中,并以更细的粒度处理异常(例如,跳过测试而不是错误)。