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

Side by Side Diff: src/scripts/generate_test_report

Issue 1756017: Color by default only if TTY stdout. Recurse into results directories. (Closed) Base URL: ssh://git@chromiumos-git/chromeos
Patch Set: Make the constant private. Created 10 years, 7 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 6
7 """Parses and displays the contents of one or more autoserv result directories. 7 """Parses and displays the contents of one or more autoserv result directories.
8 8
9 This script parses the contents of one or more autoserv results folders and 9 This script parses the contents of one or more autoserv results folders and
10 generates test reports. 10 generates test reports.
11 """ 11 """
12 12
13 13
14 import glob 14 import glob
15 import optparse 15 import optparse
16 import os 16 import os
17 import re 17 import re
18 import sys 18 import sys
19 19
20 20
21 _STDOUT_IS_TTY = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
22
23
21 class Color(object): 24 class Color(object):
22 """Conditionally wraps text in ANSI color escape sequences.""" 25 """Conditionally wraps text in ANSI color escape sequences."""
23 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) 26 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
24 BOLD = -1 27 BOLD = -1
25 COLOR_START = '\033[1;%dm' 28 COLOR_START = '\033[1;%dm'
26 BOLD_START = '\033[1m' 29 BOLD_START = '\033[1m'
27 RESET = '\033[0m' 30 RESET = '\033[0m'
28 31
29 def __init__(self, enabled=True): 32 def __init__(self, enabled=True):
30 self._enabled = enabled 33 self._enabled = enabled
(...skipping 17 matching lines...) Expand all
48 start = self.COLOR_START % (color + 30) 51 start = self.COLOR_START % (color + 30)
49 return start + text + self.RESET 52 return start + text + self.RESET
50 53
51 54
52 def Die(message): 55 def Die(message):
53 """Emits a red error message and halts execution. 56 """Emits a red error message and halts execution.
54 57
55 Args: 58 Args:
56 message: The message to be emitted before exiting. 59 message: The message to be emitted before exiting.
57 """ 60 """
58 print Color().Color(Color.RED, '\nERROR: ' + message) 61 print Color(_STDOUT_IS_TTY).Color(Color.RED, '\nERROR: ' + message)
59 sys.exit(1) 62 sys.exit(1)
60 63
61 64
62 class ReportGenerator(object): 65 class ReportGenerator(object):
63 """Collects and displays data from autoserv results directories. 66 """Collects and displays data from autoserv results directories.
64 67
65 This class collects status and performance data from one or more autoserv 68 This class collects status and performance data from one or more autoserv
66 result directories and generates test reports. 69 result directories and generates test reports.
67 """ 70 """
68 71
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 status = 'PASS' 144 status = 'PASS'
142 145
143 perf = self._CollectPerf(testdir) 146 perf = self._CollectPerf(testdir)
144 147
145 if testdir.startswith(self._options.strip): 148 if testdir.startswith(self._options.strip):
146 testdir = testdir.replace(self._options.strip, '', 1) 149 testdir = testdir.replace(self._options.strip, '', 1)
147 150
148 self._results[testdir] = {'status': status, 151 self._results[testdir] = {'status': status,
149 'perf': perf} 152 'perf': perf}
150 153
154 def _CollectResultsRec(self, resdir):
155 """Recursively collect results into the self._results dictionary.
156
157 Args:
158 resdir: results/test directory to parse results from and recurse into.
159 """
160
161 self._CollectResult(resdir)
162 for testdir in glob.glob(os.path.join(resdir, '*')):
163 self._CollectResultsRec(testdir)
164
151 def _CollectResults(self): 165 def _CollectResults(self):
152 """Parses results into the self._results dictionary. 166 """Parses results into the self._results dictionary.
153 167
154 Initializes a dictionary (self._results) with test folders as keys and 168 Initializes a dictionary (self._results) with test folders as keys and
155 result data (status, perf keyvals) as values. 169 result data (status, perf keyvals) as values.
156 """ 170 """
157 self._results = {} 171 self._results = {}
158 for resdir in self._args: 172 for resdir in self._args:
159 if not os.path.isdir(resdir): 173 if not os.path.isdir(resdir):
160 Die('\'%s\' does not exist' % resdir) 174 Die('\'%s\' does not exist' % resdir)
161 175 self._CollectResultsRec(resdir)
162 # Check the top level result directory, in case the control file or
163 # autoserv have signalled failures. Then check subdirectories.
164 self._CollectResult(resdir)
165 for testdir in glob.glob(os.path.join(resdir, '*')):
166 self._CollectResult(testdir)
167 176
168 if not self._results: 177 if not self._results:
169 Die('no test directories found') 178 Die('no test directories found')
170 179
171 def GetTestColumnWidth(self): 180 def GetTestColumnWidth(self):
172 """Returns the test column width based on the test data. 181 """Returns the test column width based on the test data.
173 182
174 Aligns the test results by formatting the test directory entry based on 183 Aligns the test results by formatting the test directory entry based on
175 the longest test directory or perf key string stored in the self._results 184 the longest test directory or perf key string stored in the self._results
176 dictionary. 185 dictionary.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 print perf_key_entry + perf_value_entry 237 print perf_key_entry + perf_value_entry
229 238
230 print line 239 print line
231 240
232 total_tests = len(tests) 241 total_tests = len(tests)
233 percent_pass = 100 * tests_pass / total_tests 242 percent_pass = 100 * tests_pass / total_tests
234 pass_str = '%d/%d (%d%%)' % (tests_pass, total_tests, percent_pass) 243 pass_str = '%d/%d (%d%%)' % (tests_pass, total_tests, percent_pass)
235 print 'Total PASS: ' + self._color.Color(Color.BOLD, pass_str) 244 print 'Total PASS: ' + self._color.Color(Color.BOLD, pass_str)
236 245
237 def Run(self): 246 def Run(self):
238 """Run report generation.""" 247 """Runs report generation."""
239 self._CollectResults() 248 self._CollectResults()
240 self._GenerateReportText() 249 self._GenerateReportText()
241 250
242 251
243 def main(): 252 def main():
244 usage = 'Usage: %prog [options] result-directories...' 253 usage = 'Usage: %prog [options] result-directories...'
245 parser = optparse.OptionParser(usage=usage) 254 parser = optparse.OptionParser(usage=usage)
246 parser.add_option('--color', dest='color', action='store_true', 255 parser.add_option('--color', dest='color', action='store_true',
247 default=True, 256 default=_STDOUT_IS_TTY,
248 help='Use color for text reports [default]') 257 help='Use color for text reports [default if TTY stdout]')
249 parser.add_option('--no-color', dest='color', action='store_false', 258 parser.add_option('--no-color', dest='color', action='store_false',
250 help='Don\'t use color for text reports') 259 help='Don\'t use color for text reports')
251 parser.add_option('--perf', dest='perf', action='store_true', 260 parser.add_option('--perf', dest='perf', action='store_true',
252 default=True, 261 default=True,
253 help='Include perf keyvals in the report [default]') 262 help='Include perf keyvals in the report [default]')
254 parser.add_option('--no-perf', dest='perf', action='store_false', 263 parser.add_option('--no-perf', dest='perf', action='store_false',
255 help='Don\'t include perf keyvals in the report') 264 help='Don\'t include perf keyvals in the report')
256 parser.add_option('--strip', dest='strip', type='string', action='store', 265 parser.add_option('--strip', dest='strip', type='string', action='store',
257 default='results.', 266 default='results.',
258 help='Strip a prefix from test directory names' 267 help='Strip a prefix from test directory names'
259 ' [default: \'%default\']') 268 ' [default: \'%default\']')
260 parser.add_option('--no-strip', dest='strip', const='', action='store_const', 269 parser.add_option('--no-strip', dest='strip', const='', action='store_const',
261 help='Don\'t strip a prefix from test directory names') 270 help='Don\'t strip a prefix from test directory names')
262 (options, args) = parser.parse_args() 271 (options, args) = parser.parse_args()
263 272
264 if not args: 273 if not args:
265 parser.print_help() 274 parser.print_help()
266 Die('no result directories provided') 275 Die('no result directories provided')
267 276
268 generator = ReportGenerator(options, args) 277 generator = ReportGenerator(options, args)
269 generator.Run() 278 generator.Run()
270 279
271 280
272 if __name__ == '__main__': 281 if __name__ == '__main__':
273 main() 282 main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698