blob: 9803a33daccb5d539a8953b5c1d6c1a9949cdb13 [file]
"""Recipe for running python tests against the given build."""
import logging
import os
from pathlib import Path
from typing import Dict, List, Union
from slave import base_recipe
from slave.step import py_env_setup_step
from slave.step import py_test_step
LOGGER = logging.getLogger(__name__)
DEFAULT_UNIT_TEST_TIMEOUT_SECONDS = 300
DEFAULT_INTEGRATION_TEST_TIMEOUT_SECONDS = 3600
DEFAULT_E2E_TEST_TIMEOUT_SECONDS = 3600
UNIT_TEST_REGEX_SUFFIX = r'.*_test\.py$'
INTEGRATION_TEST_REGEX_SUFFIX = r'.*_test_integration\.py$'
E2E_TEST_REGEX_SUFFIX = r'.*_test_case.py$'
PY3_EXCLUDED_PATH = [
'cq/buildbot-masters',
'cq/scripts/master',
]
BUILD_CONFIGS = {
'py_unittest_builder_masters': {
'project': 'builder/masters',
'py_requirements_path': 'requirements_buildbot.txt',
'py_requirements_project': 'builder/masters',
'py_packages_mirror_dir': 'python_packages',
'test_file_filter_regex': UNIT_TEST_REGEX_SUFFIX,
'test_timeout_seconds': DEFAULT_UNIT_TEST_TIMEOUT_SECONDS,
},
'py_unittest_builder_scripts': {
'project': 'builder/scripts',
'test_file_filter_regex': UNIT_TEST_REGEX_SUFFIX,
'test_timeout_seconds': DEFAULT_UNIT_TEST_TIMEOUT_SECONDS,
},
'py3_unittest_continuous_tests': {
'project': 'continuous-tests',
'py_requirements_path': 'cq/requirements_recipe3.txt',
'py_requirements_project': 'continuous-tests',
'py_packages_mirror_dir': 'python_packages',
'test_file_filter_regex': UNIT_TEST_REGEX_SUFFIX,
'test_timeout_seconds': DEFAULT_UNIT_TEST_TIMEOUT_SECONDS * 2,
'module_path_regex': '^((?!{}).)*$'.format('|'.join(PY3_EXCLUDED_PATH)),
'py3': True,
},
'py_unittest_test': {
'project': 'test',
'test_file_filter_regex': UNIT_TEST_REGEX_SUFFIX,
'test_timeout_seconds': DEFAULT_UNIT_TEST_TIMEOUT_SECONDS,
},
'py3_unittest_test': {
'project': 'test',
'test_file_filter_regex': UNIT_TEST_REGEX_SUFFIX,
'test_timeout_seconds': DEFAULT_UNIT_TEST_TIMEOUT_SECONDS * 2,
'py3': True,
'py_requirements_path': os.path.join('lab_system', 'requirements3.txt'),
},
'py_unittest_chromecast_internal': {
'project': 'chromecast/internal',
'py_requirements_path': os.path.join('lab_system', 'requirements3.txt'),
'py3': True,
# The gunittest runner filters use full, absolute file paths,
# and will search into the nested git projects within
# chromecast/internal. To avoid finding unwanted test modules, include
# a 'chromecast/internal' prefix and only search specific directories.
'test_file_filter_regex':
(r'cast/internal/(build|tools|android/build)/' +
UNIT_TEST_REGEX_SUFFIX),
'test_timeout_seconds': DEFAULT_UNIT_TEST_TIMEOUT_SECONDS,
},
'py_integration_test_chromecast_internal': {
'project': 'chromecast/internal',
'py_requirements_path': os.path.join('lab_system', 'requirements3.txt'),
'py3': True,
# The gunittest runner filters use full, absolute file paths,
# and will search into the nested git projects within
# chromecast/internal. To avoid finding unwanted test modules, include
# a 'chromecast/internal' prefix and only search specific directories.
'test_file_filter_regex':
(r'cast/internal/(build|tools|android/build)/' +
INTEGRATION_TEST_REGEX_SUFFIX),
'test_timeout_seconds': DEFAULT_INTEGRATION_TEST_TIMEOUT_SECONDS,
},
}
Config = Dict[str, Union[str, int]]
def GetValidBuildNames():
return list(BUILD_CONFIGS.keys())
def CreateRecipe(build_name: str, **kwargs):
"""Builds a recipe object."""
if build_name in BUILD_CONFIGS:
return PyTestRecipe(
config=BUILD_CONFIGS[build_name],
**kwargs)
raise base_recipe.BuildNameNotSupportedError(build_name)
class PyTestRecipe(base_recipe.BaseRecipe):
"""Recipe to run python tests on a repository."""
def __init__(self,
config: Config,
**kwargs):
super().__init__(**kwargs)
self._config = config
LOGGER.info("Eureka root when creatini PyTestRecipe: %s", self._eureka_root)
def get_steps(self):
requirements_project = self._config.get('py_requirements_project', 'test')
requirements_path = self._config.get(
'py_requirements_path', os.path.join('lab_system', 'requirements.txt'))
python_packages_dir = self._config.get(
'py_packages_mirror_dir', 'team-catatester/python_packages')
test_file_filter_regex = self._config.get(
'test_file_filter_regex', UNIT_TEST_REGEX_SUFFIX)
test_timeout_seconds = self._config.get(
'test_timeout_seconds', DEFAULT_UNIT_TEST_TIMEOUT_SECONDS)
test_py3 = self._config.get('py3', False)
module_path_regex = self._config.get('module_path_regex', '.')
LOGGER.info("Eureka root when creating additional import paths: %s", self._eureka_root)
additional_import_paths = [
self._eureka_root / path for path
in (
'builder/masters',
'builder/masters/src',
'chromium/src/third_party/catapult/telemetry',
'chromium/src/chromecast/internal',
'chromium/src/chromecast/tools',
'continuous-tests',
'continuous-tests/cq/scripts',
'test',
'testing/external/autotest',
'testing/external/chromite',
'testing/sprockets',
)]
return [
py_env_setup_step.PyEnvSetupStep(
additional_import_paths=additional_import_paths,
local_packages_dir=python_packages_dir,
py3=test_py3,
requirements_path=requirements_path,
requirements_project=requirements_project,
**self._step_kwargs),
py_test_step.PyTestStep(
project=self._config.get('project'),
test_file_filter_regex=test_file_filter_regex,
timeout=test_timeout_seconds,
module_path_regex=module_path_regex,
**self._step_kwargs)
]