1# Copyright 2017, The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Aggregates test runners, groups tests by test runners and kicks off tests.""" 16 17# pylint: disable=import-outside-toplevel 18 19from __future__ import annotations 20 21import itertools 22from typing import Any, Dict, List 23 24from atest import atest_error 25from atest import bazel_mode 26from atest import module_info 27from atest.test_finders import test_info 28from atest.test_runner_invocation import TestRunnerInvocation 29from atest.test_runners import atest_tf_test_runner 30from atest.test_runners import mobly_test_runner 31from atest.test_runners import robolectric_test_runner 32from atest.test_runners import suite_plan_test_runner 33from atest.test_runners import test_runner_base 34from atest.test_runners import vts_tf_test_runner 35 36_TEST_RUNNERS = { 37 atest_tf_test_runner.AtestTradefedTestRunner.NAME: ( 38 atest_tf_test_runner.AtestTradefedTestRunner 39 ), 40 mobly_test_runner.MoblyTestRunner.NAME: mobly_test_runner.MoblyTestRunner, 41 robolectric_test_runner.RobolectricTestRunner.NAME: ( 42 robolectric_test_runner.RobolectricTestRunner 43 ), 44 suite_plan_test_runner.SuitePlanTestRunner.NAME: ( 45 suite_plan_test_runner.SuitePlanTestRunner 46 ), 47 vts_tf_test_runner.VtsTradefedTestRunner.NAME: ( 48 vts_tf_test_runner.VtsTradefedTestRunner 49 ), 50 bazel_mode.BazelTestRunner.NAME: bazel_mode.BazelTestRunner, 51} 52 53 54def _get_test_runners(): 55 """Returns the test runners. 56 57 If external test runners are defined outside atest, they can be try-except 58 imported into here. 59 60 Returns: 61 Dict of test runner name to test runner class. 62 """ 63 test_runners_dict = _TEST_RUNNERS 64 # Example import of example test runner: 65 try: 66 from test_runners import example_test_runner 67 68 test_runners_dict[example_test_runner.ExampleTestRunner.NAME] = ( 69 example_test_runner.ExampleTestRunner 70 ) 71 except ImportError: 72 pass 73 return test_runners_dict 74 75 76def group_tests_by_test_runners(test_infos): 77 """Group the test_infos by test runners 78 79 Args: 80 test_infos: List of TestInfo. 81 82 Returns: 83 List of tuples (test runner, tests). 84 """ 85 tests_by_test_runner = [] 86 test_runner_dict = _get_test_runners() 87 key = lambda x: x.test_runner 88 sorted_test_infos = sorted(list(test_infos), key=key) 89 for test_runner, tests in itertools.groupby(sorted_test_infos, key): 90 # groupby returns a grouper object, we want to operate on a list. 91 tests = list(tests) 92 test_runner_class = test_runner_dict.get(test_runner) 93 if test_runner_class is None: 94 raise atest_error.UnknownTestRunnerError( 95 'Unknown Test Runner %s' % test_runner 96 ) 97 tests_by_test_runner.append((test_runner_class, tests)) 98 return tests_by_test_runner 99 100 101def create_test_runner_invocations( 102 *, 103 test_infos: List[test_info.TestInfo], 104 results_dir: str, 105 mod_info: module_info.ModuleInfo, 106 extra_args: Dict[str, Any], 107 minimal_build: bool, 108) -> List[TestRunnerInvocation]: 109 """Creates TestRunnerInvocation instances. 110 111 Args: 112 test_infos: A list of instances of TestInfo. 113 results_dir: A directory which stores the ATest execution information. 114 mod_info: An instance of ModuleInfo. 115 extra_args: A dict of arguments for the test runner to utilize. 116 minimal_build: A boolean setting whether or not this invocation will 117 minimize the build target set. 118 119 Returns: 120 A list of TestRunnerInvocation instances. 121 """ 122 123 test_runner_invocations = [] 124 for test_runner_class, tests in group_tests_by_test_runners(test_infos): 125 test_runner = test_runner_class( 126 results_dir, 127 mod_info=mod_info, 128 extra_args=extra_args, 129 minimal_build=minimal_build, 130 ) 131 132 test_runner_invocations.extend( 133 test_runner.create_invocations(extra_args=extra_args, test_infos=tests) 134 ) 135 136 return test_runner_invocations 137