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

Side by Side Diff: build/android/pylib/base/test_result.py

Issue 12025025: [Android] Track individual test case timeouts for gtests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | build/android/pylib/gtest/test_package.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 5
6 import json 6 import json
7 import logging 7 import logging
8 import os 8 import os
9 import re 9 import re
10 import time 10 import time
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 50
51 51
52 class TestResults(object): 52 class TestResults(object):
53 """Results of a test run.""" 53 """Results of a test run."""
54 54
55 def __init__(self): 55 def __init__(self):
56 self.ok = [] 56 self.ok = []
57 self.failed = [] 57 self.failed = []
58 self.crashed = [] 58 self.crashed = []
59 self.unknown = [] 59 self.unknown = []
60 self.timed_out = False 60 self.timed_out = []
61 self.overall_timed_out = False
61 self.overall_fail = False 62 self.overall_fail = False
62 self.device_exception = None 63 self.device_exception = None
63 64
64 @staticmethod 65 @staticmethod
65 def FromRun(ok=None, failed=None, crashed=None, timed_out=False, 66 def FromRun(ok=None, failed=None, crashed=None, timed_out=None,
66 overall_fail=False, device_exception=None): 67 overall_timed_out=False, overall_fail=False,
68 device_exception=None):
67 ret = TestResults() 69 ret = TestResults()
68 ret.ok = ok or [] 70 ret.ok = ok or []
69 ret.failed = failed or [] 71 ret.failed = failed or []
70 ret.crashed = crashed or [] 72 ret.crashed = crashed or []
71 ret.timed_out = timed_out 73 ret.timed_out = timed_out or []
74 ret.overall_timed_out = overall_timed_out
72 ret.overall_fail = overall_fail 75 ret.overall_fail = overall_fail
73 ret.device_exception = device_exception 76 ret.device_exception = device_exception
74 return ret 77 return ret
75 78
76 @staticmethod 79 @staticmethod
77 def FromTestResults(results): 80 def FromTestResults(results):
78 """Combines a list of results in a single TestResults object.""" 81 """Combines a list of results in a single TestResults object."""
79 ret = TestResults() 82 ret = TestResults()
80 for t in results: 83 for t in results:
81 ret.ok += t.ok 84 ret.ok += t.ok
82 ret.failed += t.failed 85 ret.failed += t.failed
83 ret.crashed += t.crashed 86 ret.crashed += t.crashed
84 ret.unknown += t.unknown 87 ret.unknown += t.unknown
85 if t.timed_out: 88 ret.timed_out += t.timed_out
86 ret.timed_out = True 89 if t.overall_timed_out:
90 ret.overall_timed_out = True
87 if t.overall_fail: 91 if t.overall_fail:
88 ret.overall_fail = True 92 ret.overall_fail = True
89 return ret 93 return ret
90 94
91 @staticmethod 95 @staticmethod
92 def FromPythonException(test_name, start_date_ms, exc_info): 96 def FromPythonException(test_name, start_date_ms, exc_info):
93 """Constructs a TestResults with exception information for the given test. 97 """Constructs a TestResults with exception information for the given test.
94 98
95 Args: 99 Args:
96 test_name: name of the test which raised an exception. 100 test_name: name of the test which raised an exception.
(...skipping 23 matching lines...) Expand all
120 def DeviceExceptions(results): 124 def DeviceExceptions(results):
121 return set(filter(lambda t: t.device_exception, results)) 125 return set(filter(lambda t: t.device_exception, results))
122 126
123 def _Log(self, sorted_list): 127 def _Log(self, sorted_list):
124 for t in sorted_list: 128 for t in sorted_list:
125 logging.critical(t.name) 129 logging.critical(t.name)
126 if t.log: 130 if t.log:
127 logging.critical(t.log) 131 logging.critical(t.log)
128 132
129 def GetAllBroken(self): 133 def GetAllBroken(self):
130 """Returns the all broken tests including failed, crashed, unknown.""" 134 """Returns the all broken tests."""
131 return self.failed + self.crashed + self.unknown 135 return self.failed + self.crashed + self.unknown + self.timed_out
132 136
133 def _LogToFile(self, test_type, test_suite, build_type): 137 def _LogToFile(self, test_type, test_suite, build_type):
134 """Log results to local files which can be used for aggregation later.""" 138 """Log results to local files which can be used for aggregation later."""
135 # TODO(frankf): Report tests that failed to run here too. 139 # TODO(frankf): Report tests that failed to run here too.
136 log_file_path = os.path.join(constants.CHROME_DIR, 'out', 140 log_file_path = os.path.join(constants.CHROME_DIR, 'out',
137 build_type, 'test_logs') 141 build_type, 'test_logs')
138 if not os.path.exists(log_file_path): 142 if not os.path.exists(log_file_path):
139 os.mkdir(log_file_path) 143 os.mkdir(log_file_path)
140 full_file_name = os.path.join( 144 full_file_name = os.path.join(
141 log_file_path, re.sub('\W', '_', test_type).lower() + '.log') 145 log_file_path, re.sub('\W', '_', test_type).lower() + '.log')
142 if not os.path.exists(full_file_name): 146 if not os.path.exists(full_file_name):
143 with open(full_file_name, 'w') as log_file: 147 with open(full_file_name, 'w') as log_file:
144 print >> log_file, '\n%s results for %s build %s:' % ( 148 print >> log_file, '\n%s results for %s build %s:' % (
145 test_type, os.environ.get('BUILDBOT_BUILDERNAME'), 149 test_type, os.environ.get('BUILDBOT_BUILDERNAME'),
146 os.environ.get('BUILDBOT_BUILDNUMBER')) 150 os.environ.get('BUILDBOT_BUILDNUMBER'))
147 logging.info('Writing results to %s.' % full_file_name) 151 logging.info('Writing results to %s.' % full_file_name)
148 log_contents = [' %s result : %d tests ran' % (test_suite, 152 log_contents = [' %s result : %d tests ran' % (test_suite,
149 len(self.ok) + 153 len(self.ok) +
150 len(self.failed) + 154 len(self.failed) +
151 len(self.crashed) + 155 len(self.crashed) +
156 len(self.timed_out) +
152 len(self.unknown))] 157 len(self.unknown))]
153 content_pairs = [('passed', len(self.ok)), ('failed', len(self.failed)), 158 content_pairs = [('passed', len(self.ok)),
154 ('crashed', len(self.crashed))] 159 ('failed', len(self.failed)),
160 ('crashed', len(self.crashed)),
161 ('timed_out', len(self.timed_out)),
162 ('unknown', len(self.unknown))]
155 for (result, count) in content_pairs: 163 for (result, count) in content_pairs:
156 if count: 164 if count:
157 log_contents.append(', %d tests %s' % (count, result)) 165 log_contents.append(', %d tests %s' % (count, result))
158 with open(full_file_name, 'a') as log_file: 166 with open(full_file_name, 'a') as log_file:
159 print >> log_file, ''.join(log_contents) 167 print >> log_file, ''.join(log_contents)
160 logging.info('Writing results to %s.' % full_file_name) 168 logging.info('Writing results to %s.' % full_file_name)
161 content = {'test_group': test_type, 169 content = {'test_group': test_type,
162 'ok': [t.name for t in self.ok], 170 'ok': [t.name for t in self.ok],
163 'failed': [t.name for t in self.failed], 171 'failed': [t.name for t in self.failed],
164 'crashed': [t.name for t in self.failed], 172 'crashed': [t.name for t in self.failed],
173 'timed_out': [t.name for t in self.timed_out],
165 'unknown': [t.name for t in self.unknown],} 174 'unknown': [t.name for t in self.unknown],}
166 json_file_path = os.path.join(log_file_path, 'results.json') 175 json_file_path = os.path.join(log_file_path, 'results.json')
167 with open(json_file_path, 'a') as json_file: 176 with open(json_file_path, 'a') as json_file:
168 print >> json_file, json.dumps(content) 177 print >> json_file, json.dumps(content)
169 logging.info('Writing results to %s.' % json_file_path) 178 logging.info('Writing results to %s.' % json_file_path)
170 179
171 def _LogToFlakinessDashboard(self, test_type, test_package, flakiness_server): 180 def _LogToFlakinessDashboard(self, test_type, test_package, flakiness_server):
172 """Upload results to the flakiness dashboard""" 181 """Upload results to the flakiness dashboard"""
173 logging.info('Upload results for test type "%s", test package "%s" to %s' % 182 logging.info('Upload results for test type "%s", test package "%s" to %s' %
174 (test_type, test_package, flakiness_server)) 183 (test_type, test_package, flakiness_server))
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 """ 230 """
222 # Output all broken tests or 'passed' if none broken. 231 # Output all broken tests or 'passed' if none broken.
223 logging.critical('*' * 80) 232 logging.critical('*' * 80)
224 logging.critical('Final result:') 233 logging.critical('Final result:')
225 if self.failed: 234 if self.failed:
226 logging.critical('Failed:') 235 logging.critical('Failed:')
227 self._Log(sorted(self.failed)) 236 self._Log(sorted(self.failed))
228 if self.crashed: 237 if self.crashed:
229 logging.critical('Crashed:') 238 logging.critical('Crashed:')
230 self._Log(sorted(self.crashed)) 239 self._Log(sorted(self.crashed))
240 if self.timed_out:
241 logging.critical('Timed out:')
242 self._Log(sorted(self.timed_out))
231 if self.unknown: 243 if self.unknown:
232 logging.critical('Unknown:') 244 logging.critical('Unknown:')
233 self._Log(sorted(self.unknown)) 245 self._Log(sorted(self.unknown))
234 if not self.GetAllBroken(): 246 if not self.GetAllBroken():
235 logging.critical('Passed') 247 logging.critical('Passed')
236 248
237 # Summarize in the test output. 249 # Summarize in the test output.
238 logging.critical('*' * 80) 250 logging.critical('*' * 80)
239 summary = ['Summary:\n'] 251 summary = ['Summary:\n']
240 if all_tests: 252 if all_tests:
241 summary += ['TESTS_TO_RUN=%d\n' % len(all_tests)] 253 summary += ['TESTS_TO_RUN=%d\n' % len(all_tests)]
242 num_tests_ran = (len(self.ok) + len(self.failed) + 254 num_tests_ran = (len(self.ok) + len(self.failed) +
243 len(self.crashed) + len(self.unknown)) 255 len(self.crashed) + len(self.unknown) +
256 len(self.timed_out))
244 tests_passed = [t.name for t in self.ok] 257 tests_passed = [t.name for t in self.ok]
245 tests_failed = [t.name for t in self.failed] 258 tests_failed = [t.name for t in self.failed]
246 tests_crashed = [t.name for t in self.crashed] 259 tests_crashed = [t.name for t in self.crashed]
247 tests_unknown = [t.name for t in self.unknown] 260 tests_unknown = [t.name for t in self.unknown]
261 tests_timed_out = [t.name for t in self.timed_out]
248 summary += ['RAN=%d\n' % (num_tests_ran), 262 summary += ['RAN=%d\n' % (num_tests_ran),
249 'PASSED=%d\n' % len(tests_passed), 263 'PASSED=%d\n' % len(tests_passed),
250 'FAILED=%d %s\n' % (len(tests_failed), tests_failed), 264 'FAILED=%d %s\n' % (len(tests_failed), tests_failed),
251 'CRASHED=%d %s\n' % (len(tests_crashed), tests_crashed), 265 'CRASHED=%d %s\n' % (len(tests_crashed), tests_crashed),
266 'TIMEDOUT=%d %s\n' % (len(tests_timed_out), tests_timed_out),
252 'UNKNOWN=%d %s\n' % (len(tests_unknown), tests_unknown)] 267 'UNKNOWN=%d %s\n' % (len(tests_unknown), tests_unknown)]
253 if all_tests and num_tests_ran != len(all_tests): 268 if all_tests and num_tests_ran != len(all_tests):
254 # Add the list of tests we failed to run. 269 # Add the list of tests we failed to run.
255 tests_failed_to_run = list(set(all_tests) - set(tests_passed) - 270 tests_failed_to_run = list(set(all_tests) - set(tests_passed) -
256 set(tests_failed) - set(tests_crashed) - 271 set(tests_failed) - set(tests_crashed) -
257 set(tests_unknown)) 272 set(tests_unknown) - set(tests_timed_out))
258 summary += ['FAILED_TO_RUN=%d %s\n' % (len(tests_failed_to_run), 273 summary += ['FAILED_TO_RUN=%d %s\n' % (len(tests_failed_to_run),
259 tests_failed_to_run)] 274 tests_failed_to_run)]
260 summary_string = ''.join(summary) 275 summary_string = ''.join(summary)
261 logging.critical(summary_string) 276 logging.critical(summary_string)
262 logging.critical('*' * 80) 277 logging.critical('*' * 80)
263 278
264 if os.environ.get('BUILDBOT_BUILDERNAME'): 279 if os.environ.get('BUILDBOT_BUILDERNAME'):
265 # It is possible to have multiple buildbot steps for the same 280 # It is possible to have multiple buildbot steps for the same
266 # instrumenation test package using different annotations. 281 # instrumenation test package using different annotations.
267 if annotation and len(annotation) == 1: 282 if annotation and len(annotation) == 1:
268 test_suite = annotation[0] 283 test_suite = annotation[0]
269 else: 284 else:
270 test_suite = test_package 285 test_suite = test_package
271 self._LogToFile(test_type, test_suite, build_type) 286 self._LogToFile(test_type, test_suite, build_type)
272 287
273 if flakiness_server: 288 if flakiness_server:
274 self._LogToFlakinessDashboard(test_type, test_package, flakiness_server) 289 self._LogToFlakinessDashboard(test_type, test_package, flakiness_server)
275 290
276 def PrintAnnotation(self): 291 def PrintAnnotation(self):
277 """Print buildbot annotations for test results.""" 292 """Print buildbot annotations for test results."""
278 if self.failed or self.crashed or self.overall_fail or self.timed_out: 293 if (self.failed or self.crashed or self.overall_fail or
294 self.overall_timed_out):
279 buildbot_report.PrintError() 295 buildbot_report.PrintError()
280 else: 296 else:
281 print 'Step success!' # No annotation needed 297 print 'Step success!' # No annotation needed
OLDNEW
« no previous file with comments | « no previous file | build/android/pylib/gtest/test_package.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698