diff options
author | uael <uael@google.com> | 2023-03-29 04:43:07 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-03-29 04:43:07 +0000 |
commit | 872432729fdc4a5e3efd86d57e7456fa75537b4d (patch) | |
tree | 877f01103ce47b86d9c6d5c883201c2e7220547b | |
parent | 09914f38be6a2ef6df0638065b783d17ecb3d99b (diff) | |
parent | 2b67610653d39854690f9de3ea426a94a36f02de (diff) | |
download | mobly-872432729fdc4a5e3efd86d57e7456fa75537b4d.tar.gz |
Merge remote-tracking branch 'aosp/upstream-master' into master am: fbc9ba8471 am: 2144d8a6eb am: 63728470d2 am: 2b67610653android-14.0.0_r45android-14.0.0_r44android-14.0.0_r43android-14.0.0_r42android-14.0.0_r41android-14.0.0_r40android-14.0.0_r39android-14.0.0_r38android-14.0.0_r27android-14.0.0_r26android-14.0.0_r25android-14.0.0_r24android-14.0.0_r23android-14.0.0_r22android-14.0.0_r21android-14.0.0_r20android-14.0.0_r19android-14.0.0_r18android-14.0.0_r17android-14.0.0_r16android14-qpr1-s2-releaseandroid14-qpr1-releaseandroid14-d2-s5-releaseandroid14-d2-s4-releaseandroid14-d2-s3-releaseandroid14-d2-s2-releaseandroid14-d2-s1-releaseandroid14-d2-release
Original change: https://android-review.googlesource.com/c/platform/external/python/mobly/+/2499579
Change-Id: Icccccfb21568da3ae609d6007b9a226f74603f97
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | mobly/config_parser.py | 3 | ||||
-rw-r--r-- | mobly/records.py | 1 | ||||
-rw-r--r-- | mobly/suite_runner.py | 94 | ||||
-rwxr-xr-x | tests/mobly/suite_runner_test.py | 17 |
4 files changed, 93 insertions, 22 deletions
diff --git a/mobly/config_parser.py b/mobly/config_parser.py index 0f31cdc..2f2da91 100644 --- a/mobly/config_parser.py +++ b/mobly/config_parser.py @@ -176,8 +176,7 @@ class TestRunConfig: """ def __init__(self): - # Init value is an empty string to avoid string joining errors. - self.log_path = '' + self.log_path = _DEFAULT_LOG_PATH # Deprecated, use 'testbed_name' self.test_bed_name = None self.testbed_name = None diff --git a/mobly/records.py b/mobly/records.py index 69f1f9d..b77817c 100644 --- a/mobly/records.py +++ b/mobly/records.py @@ -156,6 +156,7 @@ class TestSummaryWriter: yaml.safe_dump(new_content, f, explicit_start=True, + explicit_end=True, allow_unicode=True, indent=4) diff --git a/mobly/suite_runner.py b/mobly/suite_runner.py index 72732b5..b2b2579 100644 --- a/mobly/suite_runner.py +++ b/mobly/suite_runner.py @@ -92,22 +92,38 @@ def _parse_cli_args(argv): Namespace containing the parsed args. """ parser = argparse.ArgumentParser(description='Mobly Suite Executable.') - parser.add_argument('-c', - '--config', + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('-c', + '--config', + type=str, + metavar='<PATH>', + help='Path to the test configuration file.') + group.add_argument( + '-l', + '--list_tests', + action='store_true', + help='Print the names of the tests defined in a script without ' + 'executing them.') + parser.add_argument('--tests', + '--test_case', + nargs='+', type=str, - required=True, - metavar='<PATH>', - help='Path to the test configuration file.') - parser.add_argument( - '--tests', - '--test_case', - nargs='+', - type=str, - metavar='[ClassA[.test_a] ClassB[.test_b] ...]', - help='A list of test classes and optional tests to execute.') + metavar='[ClassA[.test_a] ClassB[.test_b] ...]', + help='A list of test classes and optional tests to execute.') + parser.add_argument('-tb', + '--test_bed', + nargs='+', + type=str, + metavar='[<TEST BED NAME1> <TEST BED NAME2> ...]', + help='Specify which test beds to run tests on.') + + parser.add_argument('-v', + '--verbose', + action='store_true', + help='Set console logger level to DEBUG') if not argv: argv = sys.argv[1:] - return parser.parse_args(argv) + return parser.parse_known_args(argv)[0] def _find_suite_class(): @@ -132,6 +148,33 @@ def _find_suite_class(): return test_suites[0] +def _print_test_names(test_classes): + """Prints the names of all the tests in all test classes. + Args: + test_classes: classes, the test classes to print names from. + """ + for test_class in test_classes: + cls = test_class(config_parser.TestRunConfig()) + test_names = [] + try: + # Executes pre-setup procedures, this is required since it might + # generate test methods that we want to return as well. + cls._pre_run() + if cls.tests: + # Specified by run list in class. + test_names = list(cls.tests) + else: + # No test method specified by user, list all in test class. + test_names = cls.get_existing_test_names() + except Exception: + logging.exception('Failed to retrieve generated tests.') + finally: + cls._clean_up() + print('==========> %s <==========' % cls.TAG) + for name in test_names: + print(f"{cls.TAG}.{name}") + + def run_suite_class(argv=None): """Executes tests in the test suite. @@ -139,17 +182,22 @@ def run_suite_class(argv=None): argv: A list that is then parsed as CLI args. If None, defaults to sys.argv. """ cli_args = _parse_cli_args(argv) - test_configs = config_parser.load_test_config_file(cli_args.config) + suite_class = _find_suite_class() + if cli_args.list_tests: + _print_test_names([suite_class]) + sys.exit(0) + test_configs = config_parser.load_test_config_file(cli_args.config, + cli_args.test_bed) config_count = len(test_configs) if config_count != 1: logging.error('Expect exactly one test config, found %d', config_count) config = test_configs[0] runner = test_runner.TestRunner( log_dir=config.log_path, testbed_name=config.testbed_name) - suite_class = _find_suite_class() suite = suite_class(runner, config) + console_level = logging.DEBUG if cli_args.verbose else logging.INFO ok = False - with runner.mobly_logger(): + with runner.mobly_logger(console_level=console_level): try: suite.setup_suite(config.copy()) try: @@ -176,8 +224,6 @@ def run_suite(test_classes, argv=None): input. """ args = _parse_cli_args(argv) - # Load test config file. - test_configs = config_parser.load_test_config_file(args.config) # Check the classes that were passed in for test_class in test_classes: @@ -187,14 +233,22 @@ def run_suite(test_classes, argv=None): 'mobly.base_test.BaseTestClass', test_class) sys.exit(1) + if args.list_tests: + _print_test_names(test_classes) + sys.exit(0) + + # Load test config file. + test_configs = config_parser.load_test_config_file(args.config, + args.test_bed) # Find the full list of tests to execute selected_tests = compute_selected_tests(test_classes, args.tests) + console_level = logging.DEBUG if args.verbose else logging.INFO # Execute the suite ok = True for config in test_configs: runner = test_runner.TestRunner(config.log_path, config.testbed_name) - with runner.mobly_logger(): + with runner.mobly_logger(console_level=console_level): for (test_class, tests) in selected_tests.items(): runner.add_test_class(config, test_class, tests) try: @@ -260,7 +314,7 @@ def compute_selected_tests(test_classes, selected_tests): test_class_name_to_tests = collections.OrderedDict() for test_name in selected_tests: if '.' in test_name: # Has a test method - (test_class_name, test_name) = test_name.split('.') + (test_class_name, test_name) = test_name.split('.', maxsplit=1) if test_class_name not in test_class_name_to_tests: # Never seen this class before test_class_name_to_tests[test_class_name] = [test_name] diff --git a/tests/mobly/suite_runner_test.py b/tests/mobly/suite_runner_test.py index 976e7ef..dabf74f 100755 --- a/tests/mobly/suite_runner_test.py +++ b/tests/mobly/suite_runner_test.py @@ -156,6 +156,23 @@ class SuiteRunnerTest(unittest.TestCase): mock_called.teardown_suite.assert_called_once_with() mock_exit.assert_not_called() + def test_print_test_names(self): + mock_test_class = mock.MagicMock() + mock_cls_instance = mock.MagicMock() + mock_test_class.return_value = mock_cls_instance + suite_runner._print_test_names([mock_test_class]) + mock_cls_instance._pre_run.assert_called_once() + mock_cls_instance._clean_up.assert_called_once() + + def test_print_test_names_with_exception(self): + mock_test_class = mock.MagicMock() + mock_cls_instance = mock.MagicMock() + mock_test_class.return_value = mock_cls_instance + suite_runner._print_test_names([mock_test_class]) + mock_cls_instance._pre_run.side_effect = Exception( + 'Something went wrong.') + mock_cls_instance._clean_up.assert_called_once() + if __name__ == "__main__": unittest.main() |