Merge "Add option to skip all remaining test cases after a given timeout is expired"

This commit is contained in:
Zuul 2021-07-10 00:15:58 +00:00 committed by Gerrit Code Review
commit 88fbfe6329
6 changed files with 71 additions and 11 deletions

View File

@ -117,6 +117,10 @@ subparsers:
type: Value
help: Test case timeout in seconds
ansible_variable: test_case_timeout
test-runner-timeout:
type: Value
help: Test runner timeout in seconds
ansible_variable: test_runner_timeout
undercloud_host:
type: Value
help: inventory hostname of the undercloud host

View File

@ -8,13 +8,15 @@ test_default_conf:
testcase:
timeout: "{{ test_case_timeout }}"
test_runner_timeout: "{{ test_runner_timeout }}"
tripleo:
undercloud_ssh_hostname: "{{ undercloud_ssh_hostname }}"
test_log_debug: false
test_case_timeout: 7200.
test_case_timeout: 1800.
test_runner_timeout: 14400.
# OpenStack client credentials
stackrc_file: '{{ ansible_user_dir }}/overcloudrc'

View File

@ -15,7 +15,7 @@ tox_step_index: 0
tox_report_name:
"{{ test_report_name }}{% if tox_step_index %}_{{ '{:02d}'.format(tox_step_index | int) }}{% endif %}{% if tox_step_name %}_{{ tox_step_name }}{% endif %}{% if tox_envlist %}_{{ tox_envlist }}{% endif %}"
tox_run_tests_timeout: 14400 # 4 hours
tox_run_tests_timeout: 18000 # 5 hours
tox_constraints_file: '{{ remote_constraints_file }}'

View File

@ -15,33 +15,51 @@ from __future__ import absolute_import
import os
import sys
import typing # noqa
import typing
from oslo_log import log
import testtools
from tobiko.common import _exception
from tobiko.common import _time
LOG = log.getLogger(__name__)
os.environ.setdefault('PYTHON', sys.executable)
class TestCaseEntry(typing.NamedTuple):
test_case: testtools.TestCase
start_time: float
class TestCasesManager(object):
start_time: _time.Seconds = None
def __init__(self):
self._test_cases: typing.List[testtools.TestCase] = []
self._test_cases: typing.List[TestCaseEntry] = []
def get_test_case(self) -> testtools.TestCase:
try:
return self._test_cases[-1]
return self._test_cases[-1].test_case
except IndexError:
return DUMMY_TEST_CASE
def pop_test_case(self) -> testtools.TestCase:
return self._test_cases.pop()
entry = self._test_cases.pop()
elapsed_time = _time.time() - entry.start_time
LOG.debug(f"Exit test case '{entry.test_case.id()}' after "
f"{elapsed_time} seconds")
return entry.test_case
def push_test_case(self, test_case: testtools.TestCase):
_exception.check_valid_type(test_case, testtools.TestCase)
self._test_cases.append(test_case)
entry = TestCaseEntry(test_case=test_case,
start_time=_time.time())
self._test_cases.append(entry)
LOG.debug(f"Enter test case '{test_case.id()}'")
TEST_CASES = TestCasesManager()

View File

@ -66,7 +66,11 @@ TESTCASE_OPTIONS = [
cfg.FloatOpt('timeout',
default=None,
help=("Timeout (in seconds) used for interrupting test case "
"execution"))]
"execution")),
cfg.FloatOpt('test_runner_timeout',
default=None,
help=("Timeout (in seconds) used for interrupting test "
"runner execution"))]
def workspace_config_files(project=None, prog=None):

View File

@ -22,6 +22,7 @@ from oslo_log import log
from py.xml import html # pylint: disable=no-name-in-module,import-error
import pytest
import tobiko
LOG = log.getLogger(__name__)
@ -47,7 +48,6 @@ def configure_metadata(config):
def configure_caplog(config):
import tobiko
tobiko_config = tobiko.tobiko_config()
if tobiko_config.logging.capture_log is True:
@ -93,8 +93,40 @@ def set_default_inicfg(config, key, default):
LOG.debug(f"Keep existing inicfg: {key} = {value}")
class TestRunnerTimeoutManager(tobiko.SharedFixture):
timeout: tobiko.Seconds = None
deadline: tobiko.Seconds = None
def setup_fixture(self):
tobiko_config = tobiko.tobiko_config()
self.timeout = tobiko_config.testcase.test_runner_timeout
if self.timeout is None:
LOG.info('Test runner timeout is disabled')
else:
LOG.info('Test runner timeout is enabled: '
f'timeout is {self.timeout} seconds')
self.deadline = tobiko.time() + self.timeout
@classmethod
def check_test_runner_timeout(cls):
self = tobiko.setup_fixture(cls)
if self.deadline is not None:
time_left = self.deadline - tobiko.time()
if time_left <= 0.:
pytest.skip(
f"Test runner execution timed out after {self.timeout} "
f"seconds",
allow_module_level=True)
else:
LOG.debug('Test runner timeout is enabled: '
f'{time_left} seconds left')
def check_test_runner_timeout():
TestRunnerTimeoutManager.check_test_runner_timeout()
def configure_timeout(config):
import tobiko
tobiko_config = tobiko.tobiko_config()
default = tobiko_config.testcase.timeout
if default is not None and default > 0.:
@ -128,7 +160,7 @@ def pytest_html_report_title(report):
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_call(item):
# pylint: disable=protected-access
import tobiko
check_test_runner_timeout()
tobiko.push_test_case(item._testcase)
try:
yield