Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(508)

Side by Side Diff: build/android/test_runner.py

Issue 2933993002: Add local results details pages.
Patch Set: Add --local-output arg which enables local results detail pages. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright 2013 The Chromium Authors. All rights reserved. 3 # Copyright 2013 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """Runs all types of tests from one unified interface.""" 7 """Runs all types of tests from one unified interface."""
8 8
9 import argparse 9 import argparse
10 import collections 10 import collections
11 import contextlib 11 import contextlib
12 import itertools 12 import itertools
13 import logging 13 import logging
14 import os 14 import os
15 import shutil 15 import shutil
16 import signal 16 import signal
17 import sys 17 import sys
18 import tempfile
18 import threading 19 import threading
19 import traceback 20 import traceback
20 import unittest 21 import unittest
21 22
22 # Import _strptime before threaded code. datetime.datetime.strptime is 23 # Import _strptime before threaded code. datetime.datetime.strptime is
23 # threadsafe except for the initial import of the _strptime module. 24 # threadsafe except for the initial import of the _strptime module.
24 # See http://crbug.com/724524 and https://bugs.python.org/issue7980. 25 # See http://crbug.com/724524 and https://bugs.python.org/issue7980.
25 import _strptime # pylint: disable=unused-import 26 import _strptime # pylint: disable=unused-import
26 27
27 from pylib.constants import host_paths 28 from pylib.constants import host_paths
28 29
29 if host_paths.DEVIL_PATH not in sys.path: 30 if host_paths.DEVIL_PATH not in sys.path:
30 sys.path.append(host_paths.DEVIL_PATH) 31 sys.path.append(host_paths.DEVIL_PATH)
31 32
32 from devil import base_error 33 from devil import base_error
33 from devil.utils import reraiser_thread 34 from devil.utils import reraiser_thread
34 from devil.utils import run_tests_helper 35 from devil.utils import run_tests_helper
35 36
36 from pylib import constants 37 from pylib import constants
37 from pylib.base import base_test_result 38 from pylib.base import base_test_result
38 from pylib.base import environment_factory 39 from pylib.base import environment_factory
40 from pylib.base import output_manager
41 from pylib.base import output_manager_factory
39 from pylib.base import test_instance_factory 42 from pylib.base import test_instance_factory
40 from pylib.base import test_run_factory 43 from pylib.base import test_run_factory
41 from pylib.results import json_results 44 from pylib.results import json_results
42 from pylib.results import report_results 45 from pylib.results import report_results
46 from pylib.results.presentation import test_results_presentation
43 from pylib.utils import logdog_helper 47 from pylib.utils import logdog_helper
44 from pylib.utils import logging_utils 48 from pylib.utils import logging_utils
45 49
46 from py_utils import contextlib_ext 50 from py_utils import contextlib_ext
47 51
48 52
49 _DEVIL_STATIC_CONFIG_FILE = os.path.abspath(os.path.join( 53 _DEVIL_STATIC_CONFIG_FILE = os.path.abspath(os.path.join(
50 host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'devil_config.json')) 54 host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'devil_config.json'))
51 55
52 56
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 help='Run the test scripts in platform mode, which ' 138 help='Run the test scripts in platform mode, which '
135 'conceptually separates the test runner from the ' 139 'conceptually separates the test runner from the '
136 '"device" (local or remote, real or emulated) on ' 140 '"device" (local or remote, real or emulated) on '
137 'which the tests are running. [experimental]') 141 'which the tests are running. [experimental]')
138 142
139 parser.add_argument( 143 parser.add_argument(
140 '-e', '--environment', 144 '-e', '--environment',
141 default='local', choices=constants.VALID_ENVIRONMENTS, 145 default='local', choices=constants.VALID_ENVIRONMENTS,
142 help='Test environment to run in (default: %(default)s).') 146 help='Test environment to run in (default: %(default)s).')
143 147
148 parser.add_argument(
149 '--local-output', action='store_true',
150 help='Whether to archive test output locally and generate '
151 'a local results detail page.')
152
144 class FastLocalDevAction(argparse.Action): 153 class FastLocalDevAction(argparse.Action):
145 def __call__(self, parser, namespace, values, option_string=None): 154 def __call__(self, parser, namespace, values, option_string=None):
146 namespace.verbose_count = max(namespace.verbose_count, 1) 155 namespace.verbose_count = max(namespace.verbose_count, 1)
147 namespace.num_retries = 0 156 namespace.num_retries = 0
148 namespace.enable_device_cache = True 157 namespace.enable_device_cache = True
149 namespace.enable_concurrent_adb = True 158 namespace.enable_concurrent_adb = True
150 namespace.skip_clear_data = True 159 namespace.skip_clear_data = True
151 namespace.extract_test_list_from_filter = True 160 namespace.extract_test_list_from_filter = True
152 161
153 parser.add_argument( 162 parser.add_argument(
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 logging.critical( 808 logging.critical(
800 'Logcat: %s', logdog_helper.get_viewer_url('unified_logcats')) 809 'Logcat: %s', logdog_helper.get_viewer_url('unified_logcats'))
801 810
802 811
803 logcats_uploader = contextlib_ext.Optional( 812 logcats_uploader = contextlib_ext.Optional(
804 upload_logcats_file(), 813 upload_logcats_file(),
805 'upload_logcats_file' in args and args.upload_logcats_file) 814 'upload_logcats_file' in args and args.upload_logcats_file)
806 815
807 ### Set up test objects. 816 ### Set up test objects.
808 817
809 env = environment_factory.CreateEnvironment(args, infra_error) 818 out_manager = output_manager_factory.CreateOutputManager(args)
819 env = environment_factory.CreateEnvironment(
820 args, out_manager, infra_error)
810 test_instance = test_instance_factory.CreateTestInstance(args, infra_error) 821 test_instance = test_instance_factory.CreateTestInstance(args, infra_error)
811 test_run = test_run_factory.CreateTestRun( 822 test_run = test_run_factory.CreateTestRun(
812 args, env, test_instance, infra_error) 823 args, env, test_instance, infra_error)
813 824
814 ### Run. 825 ### Run.
815 826
816 with json_writer, logcats_uploader, env, test_instance, test_run: 827 with json_writer, logcats_uploader, out_manager, env, test_instance, test_run:
817 828
818 repetitions = (xrange(args.repeat + 1) if args.repeat >= 0 829 repetitions = (xrange(args.repeat + 1) if args.repeat >= 0
819 else itertools.count()) 830 else itertools.count())
820 result_counts = collections.defaultdict( 831 result_counts = collections.defaultdict(
821 lambda: collections.defaultdict(int)) 832 lambda: collections.defaultdict(int))
822 iteration_count = 0 833 iteration_count = 0
823 for _ in repetitions: 834 for _ in repetitions:
824 raw_results = test_run.RunTests() 835 raw_results = test_run.RunTests()
825 if not raw_results: 836 if not raw_results:
826 continue 837 continue
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 ', '.join('%s %s' % (str(result_counts[test_name][i]), i) 874 ', '.join('%s %s' % (str(result_counts[test_name][i]), i)
864 for i in base_test_result.ResultType.GetTypes())) 875 for i in base_test_result.ResultType.GetTypes()))
865 else: 876 else:
866 all_pass += 1 877 all_pass += 1
867 878
868 logging.critical('%s of %s tests passed in all %s runs', 879 logging.critical('%s of %s tests passed in all %s runs',
869 str(all_pass), 880 str(all_pass),
870 str(tot_tests), 881 str(tot_tests),
871 str(iteration_count)) 882 str(iteration_count))
872 883
884 if args.local_output:
885 try:
886 results_detail_file = tempfile.NamedTemporaryFile(delete=False)
887 result_html_string = test_results_presentation.result_details(
888 json_path=args.json_results_file,
889 test_name=args.command,
890 cs_base_url='http://cs.chromium.org',
891 local_output=True)
892 results_detail_file.write(result_html_string)
893 results_detail_file.flush()
894 finally:
895 results_detail_link = out_manager.ArchiveAndDeleteFile(
896 results_detail_file.name,
897 'test_results_presentation.html',
898 'test_results_presentation',
899 output_manager.Datatype.HTML)
900 logging.critical('TEST RESULTS: %s', results_detail_link)
901
873 if args.command == 'perf' and (args.steps or args.single_step): 902 if args.command == 'perf' and (args.steps or args.single_step):
874 return 0 903 return 0
875 904
876 return (0 if all(r.DidRunPass() for r in all_iteration_results) 905 return (0 if all(r.DidRunPass() for r in all_iteration_results)
877 else constants.ERROR_EXIT_CODE) 906 else constants.ERROR_EXIT_CODE)
878 907
879 908
880 def DumpThreadStacks(_signal, _frame): 909 def DumpThreadStacks(_signal, _frame):
881 for thread in threading.enumerate(): 910 for thread in threading.enumerate():
882 reraiser_thread.LogThreadStack(thread) 911 reraiser_thread.LogThreadStack(thread)
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
963 if e.is_infra_error: 992 if e.is_infra_error:
964 return constants.INFRA_EXIT_CODE 993 return constants.INFRA_EXIT_CODE
965 return constants.ERROR_EXIT_CODE 994 return constants.ERROR_EXIT_CODE
966 except: # pylint: disable=W0702 995 except: # pylint: disable=W0702
967 logging.exception('Unrecognized error occurred.') 996 logging.exception('Unrecognized error occurred.')
968 return constants.ERROR_EXIT_CODE 997 return constants.ERROR_EXIT_CODE
969 998
970 999
971 if __name__ == '__main__': 1000 if __name__ == '__main__':
972 sys.exit(main()) 1001 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698