##// END OF EJS Templates
run-tests: add color to the progress output...
marmoute -
r52730:7933bcb0 default
parent child Browse files
Show More
@@ -114,36 +114,73 try: # is pygments installed
114 except ImportError:
114 except ImportError:
115 pass
115 pass
116
116
117 progress_type = {}
118
117 if pygmentspresent:
119 if pygmentspresent:
120 _T_ERROR = token.string_to_tokentype("Token.Generic.Error")
121 _T_FAILED = token.string_to_tokentype("Token.Generic.Failed")
122 _T_FNAME = token.string_to_tokentype("Token.Generic.FName")
123 _T_IGNORED = token.string_to_tokentype("Token.Generic.Ignored")
124 _T_SKIPPED = token.string_to_tokentype("Token.Generic.Skipped")
125 _T_SNAME = token.string_to_tokentype("Token.Generic.SName")
126 _T_SKIPPED_DOT = token.string_to_tokentype("Token.Generic.SkippedDot")
127 _T_SUCCESS = token.string_to_tokentype("Token.Generic.Success")
128 _T_TIMEDOUT = token.string_to_tokentype("Token.Generic.TimedOut")
118
129
119 class TestRunnerStyle(style.Style):
130 class TestRunnerStyle(style.Style):
120 default_style = ""
131 default_style = ""
121 skipped = token.string_to_tokentype("Token.Generic.Skipped")
122 failed = token.string_to_tokentype("Token.Generic.Failed")
123 skippedname = token.string_to_tokentype("Token.Generic.SName")
124 failedname = token.string_to_tokentype("Token.Generic.FName")
125 styles = {
132 styles = {
126 skipped: '#e5e5e5',
133 _T_ERROR: '#cd00cd',
127 skippedname: '#00ffff',
134 _T_FAILED: '#7f0000',
128 failed: '#7f0000',
135 _T_FNAME: '#ff0000',
129 failedname: '#ff0000',
136 _T_IGNORED: '#cdcd00',
137 _T_SKIPPED: '#e5e5e5',
138 _T_SNAME: '#00ffff',
139 _T_SKIPPED_DOT: '#00ffff',
140 _T_SUCCESS: '#00cd00',
141 _T_TIMEDOUT: '#ff00ff',
130 }
142 }
131
143
132 class TestRunnerLexer(lexer.RegexLexer):
144 class TestRunnerLexer(lexer.RegexLexer):
133 testpattern = r'[\w-]+\.(t|py)(#[a-zA-Z0-9_\-\.]+)?'
145 testpattern = r'[\w-]+\.(t|py)(#[a-zA-Z0-9_\-\.]+)?'
134 tokens = {
146 tokens = {
135 'root': [
147 'root': [
136 (r'^Skipped', token.Generic.Skipped, 'skipped'),
148 (r'^Skipped', _T_SKIPPED, 'skipped'),
137 (r'^Failed ', token.Generic.Failed, 'failed'),
149 (r'^Failed ', _T_FAILED, 'failed'),
138 (r'^ERROR: ', token.Generic.Failed, 'failed'),
150 (r'^ERROR: ', _T_FAILED, 'failed'),
139 ],
151 ],
140 'skipped': [
152 'skipped': [
141 (testpattern, token.Generic.SName),
153 (testpattern, _T_SNAME),
142 (r':.*', token.Generic.Skipped),
154 (r':.*', _T_SKIPPED),
143 ],
155 ],
144 'failed': [
156 'failed': [
145 (testpattern, token.Generic.FName),
157 (testpattern, _T_FNAME),
146 (r'(:| ).*', token.Generic.Failed),
158 (r'(:| ).*', _T_FAILED),
159 ],
160 }
161
162 progress_type['.'] = _T_SUCCESS
163 progress_type['s'] = _T_SKIPPED_DOT
164 progress_type['i'] = _T_IGNORED
165 progress_type['!'] = _T_FAILED
166 progress_type['E'] = _T_ERROR
167 progress_type['t'] = _T_TIMEDOUT
168
169 class progressLexer(lexer.RegexLexer):
170 testpattern = r'[\w-]+\.(t|py)(#[a-zA-Z0-9_\-\.]+)?'
171 tokens = {
172 'root': [
173 (r'^Skipped', _T_SKIPPED, 'skipped'),
174 (r'^Failed ', _T_FAILED, 'failed'),
175 (r'^ERROR: ', _T_FAILED, 'failed'),
176 ],
177 'skipped': [
178 (testpattern, _T_SNAME),
179 (r':.*', _T_SKIPPED),
180 ],
181 'failed': [
182 (testpattern, _T_FNAME),
183 (r'(:| ).*', _T_FAILED),
147 ],
184 ],
148 }
185 }
149
186
@@ -947,6 +984,20 def highlightmsg(msg, color):
947 return pygments.highlight(msg, runnerlexer, runnerformatter)
984 return pygments.highlight(msg, runnerlexer, runnerformatter)
948
985
949
986
987 def highlight_progress(progress, color):
988 if not color:
989 return progress
990 assert pygmentspresent
991 token = progress_type.get(progress)
992 if token is None:
993 return progress
994 style = runnerformatter.style_string.get(str(token))
995 if style is None:
996 return progress
997 else:
998 return style[0] + progress + style[1]
999
1000
950 def terminate(proc):
1001 def terminate(proc):
951 """Terminate subprocess"""
1002 """Terminate subprocess"""
952 vlog('# Terminating process %d' % proc.pid)
1003 vlog('# Terminating process %d' % proc.pid)
@@ -2266,6 +2317,12 class TestResult(base_class):
2266 else: # 'always', for testing purposes
2317 else: # 'always', for testing purposes
2267 self.color = pygmentspresent
2318 self.color = pygmentspresent
2268
2319
2320 def _write_dot(self, progress):
2321 """write an item of the "dot" progress"""
2322 formated = highlight_progress(progress, self.color)
2323 self.stream.write(formated)
2324 self.stream.flush()
2325
2269 def onStart(self, test):
2326 def onStart(self, test):
2270 """Can be overriden by custom TestResult"""
2327 """Can be overriden by custom TestResult"""
2271
2328
@@ -2280,24 +2337,33 class TestResult(base_class):
2280 else:
2337 else:
2281 with iolock:
2338 with iolock:
2282 if reason == "timed out":
2339 if reason == "timed out":
2283 self.stream.write('t')
2340 self._write_dot('t')
2284 else:
2341 else:
2285 if not self._options.nodiff:
2342 if not self._options.nodiff:
2286 self.stream.write('\n')
2343 self.stream.write('\n')
2287 # Exclude the '\n' from highlighting to lex correctly
2344 # Exclude the '\n' from highlighting to lex correctly
2288 formatted = 'ERROR: %s output changed\n' % test
2345 formatted = 'ERROR: %s output changed\n' % test
2289 self.stream.write(highlightmsg(formatted, self.color))
2346 self.stream.write(highlightmsg(formatted, self.color))
2290 self.stream.write('!')
2347 self._write_dot('!')
2291
2348
2292 self.stream.flush()
2349 self.stream.flush()
2293
2350
2294 def addSuccess(self, test):
2351 def addSuccess(self, test):
2295 with iolock:
2352 with iolock:
2296 super(TestResult, self).addSuccess(test)
2353 # bypass the TextTestResult method as do deal with the output ourself
2354 super(base_class, self).addSuccess(test)
2355 if self.showAll:
2356 self._write_status(test, "ok")
2357 elif self.dots:
2358 self._write_dot('.')
2297 self.successes.append(test)
2359 self.successes.append(test)
2298
2360
2299 def addError(self, test, err):
2361 def addError(self, test, err):
2300 super(TestResult, self).addError(test, err)
2362 super(base_class, self).addError(test, err)
2363 if self.showAll:
2364 self._write_status(test, "ERROR")
2365 elif self.dots:
2366 self._write_dot('E')
2301 if self._options.first:
2367 if self._options.first:
2302 self.stop()
2368 self.stop()
2303
2369
@@ -2308,8 +2374,7 class TestResult(base_class):
2308 if self.showAll:
2374 if self.showAll:
2309 self.stream.writeln('skipped %s' % reason)
2375 self.stream.writeln('skipped %s' % reason)
2310 else:
2376 else:
2311 self.stream.write('s')
2377 self._write_dot('s')
2312 self.stream.flush()
2313
2378
2314 def addIgnore(self, test, reason):
2379 def addIgnore(self, test, reason):
2315 self.ignored.append((test, reason))
2380 self.ignored.append((test, reason))
@@ -2318,10 +2383,9 class TestResult(base_class):
2318 self.stream.writeln('ignored %s' % reason)
2383 self.stream.writeln('ignored %s' % reason)
2319 else:
2384 else:
2320 if reason not in ('not retesting', "doesn't match keyword"):
2385 if reason not in ('not retesting', "doesn't match keyword"):
2321 self.stream.write('i')
2386 self._write_dot('i')
2322 else:
2387 else:
2323 self.testsRun += 1
2388 self.testsRun += 1
2324 self.stream.flush()
2325
2389
2326 def addOutputMismatch(self, test, ret, got, expected):
2390 def addOutputMismatch(self, test, ret, got, expected):
2327 """Record a mismatch in test output for a particular test."""
2391 """Record a mismatch in test output for a particular test."""
@@ -191,7 +191,7 test diff colorisation
191 \x1b[38;5;34m+ foo\x1b[39m (esc) (no-pygments211 !)
191 \x1b[38;5;34m+ foo\x1b[39m (esc) (no-pygments211 !)
192
192
193 \x1b[38;5;88mERROR: \x1b[39m\x1b[38;5;9mtest-failure.t\x1b[39m\x1b[38;5;88m output changed\x1b[39m (esc)
193 \x1b[38;5;88mERROR: \x1b[39m\x1b[38;5;9mtest-failure.t\x1b[39m\x1b[38;5;88m output changed\x1b[39m (esc)
194 !
194 \x1b[38;5;88m!\x1b[39m (esc)
195 \x1b[38;5;88mFailed \x1b[39m\x1b[38;5;9mtest-failure.t\x1b[39m\x1b[38;5;88m: output changed\x1b[39m (esc)
195 \x1b[38;5;88mFailed \x1b[39m\x1b[38;5;9mtest-failure.t\x1b[39m\x1b[38;5;88m: output changed\x1b[39m (esc)
196 # Ran 1 tests, 0 skipped, 1 failed.
196 # Ran 1 tests, 0 skipped, 1 failed.
197 python hash seed: * (glob)
197 python hash seed: * (glob)
General Comments 0
You need to be logged in to leave comments. Login now