OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library test.runner.reporter.compact; | 5 library test.runner.reporter.compact; |
6 | 6 |
7 import 'dart:io'; | 7 import 'dart:io'; |
8 import 'dart:isolate'; | 8 import 'dart:isolate'; |
9 | 9 |
10 import '../../backend/live_test.dart'; | 10 import '../../backend/live_test.dart'; |
11 import '../../backend/state.dart'; | 11 import '../../backend/state.dart'; |
12 import '../../utils.dart'; | 12 import '../../utils.dart'; |
13 import '../engine.dart'; | 13 import '../engine.dart'; |
14 import '../load_exception.dart'; | 14 import '../load_exception.dart'; |
| 15 import '../load_suite.dart'; |
15 | 16 |
16 /// The maximum console line length. | 17 /// The maximum console line length. |
17 /// | 18 /// |
18 /// Lines longer than this will be cropped. | 19 /// Lines longer than this will be cropped. |
19 const _lineLength = 100; | 20 const _lineLength = 100; |
20 | 21 |
21 /// A reporter that prints test results to the console in a single | 22 /// A reporter that prints test results to the console in a single |
22 /// continuously-updating line. | 23 /// continuously-updating line. |
23 class CompactReporter { | 24 class CompactReporter { |
24 /// Whether the reporter should emit terminal color escapes. | 25 /// Whether the reporter should emit terminal color escapes. |
25 final bool _color; | 26 final bool _color; |
26 | 27 |
27 /// The terminal escape for green text, or the empty string if this is Windows | 28 /// The terminal escape for green text, or the empty string if this is Windows |
28 /// or not outputting to a terminal. | 29 /// or not outputting to a terminal. |
29 final String _green; | 30 final String _green; |
30 | 31 |
31 /// The terminal escape for red text, or the empty string if this is Windows | 32 /// The terminal escape for red text, or the empty string if this is Windows |
32 /// or not outputting to a terminal. | 33 /// or not outputting to a terminal. |
33 final String _red; | 34 final String _red; |
34 | 35 |
35 /// The terminal escape for yellow text, or the empty string if this is | 36 /// The terminal escape for yellow text, or the empty string if this is |
36 /// Windows or not outputting to a terminal. | 37 /// Windows or not outputting to a terminal. |
37 final String _yellow; | 38 final String _yellow; |
38 | 39 |
| 40 /// The terminal escape for gray text, or the empty string if this is |
| 41 /// Windows or not outputting to a terminal. |
| 42 final String _gray; |
| 43 |
| 44 /// The terminal escape for bold text, or the empty string if this is |
| 45 /// Windows or not outputting to a terminal. |
| 46 final String _bold; |
| 47 |
39 /// The terminal escape for removing test coloring, or the empty string if | 48 /// The terminal escape for removing test coloring, or the empty string if |
40 /// this is Windows or not outputting to a terminal. | 49 /// this is Windows or not outputting to a terminal. |
41 final String _noColor; | 50 final String _noColor; |
42 | 51 |
43 /// Whether to use verbose stack traces. | 52 /// Whether to use verbose stack traces. |
44 final bool _verboseTrace; | 53 final bool _verboseTrace; |
45 | 54 |
46 /// The engine used to run the tests. | 55 /// The engine used to run the tests. |
47 final Engine _engine; | 56 final Engine _engine; |
48 | 57 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 | 101 |
93 CompactReporter._(this._engine, {bool color: true, bool verboseTrace: false, | 102 CompactReporter._(this._engine, {bool color: true, bool verboseTrace: false, |
94 bool printPath: true, bool printPlatform: true}) | 103 bool printPath: true, bool printPlatform: true}) |
95 : _verboseTrace = verboseTrace, | 104 : _verboseTrace = verboseTrace, |
96 _printPath = printPath, | 105 _printPath = printPath, |
97 _printPlatform = printPlatform, | 106 _printPlatform = printPlatform, |
98 _color = color, | 107 _color = color, |
99 _green = color ? '\u001b[32m' : '', | 108 _green = color ? '\u001b[32m' : '', |
100 _red = color ? '\u001b[31m' : '', | 109 _red = color ? '\u001b[31m' : '', |
101 _yellow = color ? '\u001b[33m' : '', | 110 _yellow = color ? '\u001b[33m' : '', |
| 111 _gray = color ? '\u001b[1;30m' : '', |
| 112 _bold = color ? '\u001b[1m' : '', |
102 _noColor = color ? '\u001b[0m' : '' { | 113 _noColor = color ? '\u001b[0m' : '' { |
103 _engine.onTestStarted.listen(_onTestStarted); | 114 _engine.onTestStarted.listen(_onTestStarted); |
104 _engine.success.then(_onDone); | 115 _engine.success.then(_onDone); |
105 } | 116 } |
106 | 117 |
107 /// A callback called when the engine begins running [liveTest]. | 118 /// A callback called when the engine begins running [liveTest]. |
108 void _onTestStarted(LiveTest liveTest) { | 119 void _onTestStarted(LiveTest liveTest) { |
109 if (!_stopwatch.isRunning) _stopwatch.start(); | 120 if (!_stopwatch.isRunning) _stopwatch.start(); |
110 | 121 |
111 // If this is the first test to start, print a progress line so the user | 122 // If this is the first test to start, print a progress line so the user |
112 // knows what's running. | 123 // knows what's running. It's possible that the active test may not be |
113 if (_engine.active.length == 1) _progressLine(_description(liveTest)); | 124 // [liveTest] because the engine doesn't always surface load tests. |
| 125 if (_engine.active.length == 1 && _engine.active.first == liveTest) { |
| 126 _progressLine(_description(liveTest)); |
| 127 } |
114 _printedNewline = false; | 128 _printedNewline = false; |
115 | 129 |
116 liveTest.onStateChange.listen((state) => _onStateChange(liveTest, state)); | 130 liveTest.onStateChange.listen((state) => _onStateChange(liveTest, state)); |
117 | 131 |
118 liveTest.onError.listen((error) => | 132 liveTest.onError.listen((error) => |
119 _onError(liveTest, error.error, error.stackTrace)); | 133 _onError(liveTest, error.error, error.stackTrace)); |
120 | 134 |
121 liveTest.onPrint.listen((line) { | 135 liveTest.onPrint.listen((line) { |
122 _progressLine(_description(liveTest)); | 136 _progressLine(_description(liveTest)); |
123 if (!_printedNewline) print(''); | 137 if (!_printedNewline) print(''); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 // tests finished running, probably because of a signal from the user. We | 199 // tests finished running, probably because of a signal from the user. We |
186 // shouldn't print summary information, we should just make sure the | 200 // shouldn't print summary information, we should just make sure the |
187 // terminal cursor is on its own line. | 201 // terminal cursor is on its own line. |
188 if (success == null) { | 202 if (success == null) { |
189 if (!_printedNewline) print(""); | 203 if (!_printedNewline) print(""); |
190 _printedNewline = true; | 204 _printedNewline = true; |
191 return; | 205 return; |
192 } | 206 } |
193 | 207 |
194 if (_engine.liveTests.isEmpty) { | 208 if (_engine.liveTests.isEmpty) { |
195 if (!_printedNewline) print(""); | 209 if (!_printedNewline) stdout.write("\r"); |
196 print("No tests ran."); | 210 var message = "No tests ran."; |
| 211 stdout.write(message); |
| 212 |
| 213 // Add extra padding to overwrite any load messages. |
| 214 if (!_printedNewline) stdout.write(" " * (_lineLength - message.length)); |
| 215 stdout.writeln(); |
197 } else if (!success) { | 216 } else if (!success) { |
198 _progressLine('Some tests failed.', color: _red); | 217 _progressLine('Some tests failed.', color: _red); |
199 print(''); | 218 print(''); |
200 } else if (_engine.passed.isEmpty) { | 219 } else if (_engine.passed.isEmpty) { |
201 _progressLine("All tests skipped."); | 220 _progressLine("All tests skipped."); |
202 print(''); | 221 print(''); |
203 } else { | 222 } else { |
204 _progressLine("All tests passed!"); | 223 _progressLine("All tests passed!"); |
205 print(''); | 224 print(''); |
206 } | 225 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 buffer.write(_engine.failed.length); | 268 buffer.write(_engine.failed.length); |
250 buffer.write(_noColor); | 269 buffer.write(_noColor); |
251 } | 270 } |
252 | 271 |
253 buffer.write(': '); | 272 buffer.write(': '); |
254 buffer.write(color); | 273 buffer.write(color); |
255 | 274 |
256 // Ensure the line fits within [_lineLength]. [buffer] includes the color | 275 // Ensure the line fits within [_lineLength]. [buffer] includes the color |
257 // escape sequences too. Because these sequences are not visible characters, | 276 // escape sequences too. Because these sequences are not visible characters, |
258 // we make sure they are not counted towards the limit. | 277 // we make sure they are not counted towards the limit. |
259 var nonVisible = 1 + _green.length + _noColor.length + color.length + | 278 var length = withoutColors(buffer.toString()).length; |
260 (_engine.failed.isEmpty ? 0 : _red.length + _noColor.length); | |
261 var length = buffer.length - nonVisible; | |
262 buffer.write(truncate(message, _lineLength - length)); | 279 buffer.write(truncate(message, _lineLength - length)); |
263 buffer.write(_noColor); | 280 buffer.write(_noColor); |
264 | 281 |
265 // Pad the rest of the line so that it looks erased. | 282 // Pad the rest of the line so that it looks erased. |
266 length = buffer.length - nonVisible - _noColor.length; | 283 buffer.write(' ' * (_lineLength - withoutColors(buffer.toString()).length)); |
267 buffer.write(' ' * (_lineLength - length)); | |
268 stdout.write(buffer.toString()); | 284 stdout.write(buffer.toString()); |
269 return true; | 285 return true; |
270 } | 286 } |
271 | 287 |
272 /// Returns a representation of [duration] as `MM:SS`. | 288 /// Returns a representation of [duration] as `MM:SS`. |
273 String _timeString(Duration duration) { | 289 String _timeString(Duration duration) { |
274 return "${duration.inMinutes.toString().padLeft(2, '0')}:" | 290 return "${duration.inMinutes.toString().padLeft(2, '0')}:" |
275 "${(duration.inSeconds % 60).toString().padLeft(2, '0')}"; | 291 "${(duration.inSeconds % 60).toString().padLeft(2, '0')}"; |
276 } | 292 } |
277 | 293 |
278 /// Returns a description of [liveTest]. | 294 /// Returns a description of [liveTest]. |
279 /// | 295 /// |
280 /// This differs from the test's own description in that it may also include | 296 /// This differs from the test's own description in that it may also include |
281 /// the suite's name. | 297 /// the suite's name. |
282 String _description(LiveTest liveTest) { | 298 String _description(LiveTest liveTest) { |
283 var name = liveTest.test.name; | 299 var name = liveTest.test.name; |
284 | 300 |
285 if (_printPath && liveTest.suite.path != null) { | 301 if (_printPath && liveTest.suite.path != null) { |
286 name = "${liveTest.suite.path}: $name"; | 302 name = "${liveTest.suite.path}: $name"; |
287 } | 303 } |
288 | 304 |
289 if (_printPlatform && liveTest.suite.platform != null) { | 305 if (_printPlatform && liveTest.suite.platform != null) { |
290 name = "[${liveTest.suite.platform}] $name"; | 306 name = "[${liveTest.suite.platform}] $name"; |
291 } | 307 } |
292 | 308 |
| 309 if (liveTest.suite is LoadSuite) name = "$_bold$_gray$name$_noColor"; |
| 310 |
293 return name; | 311 return name; |
294 } | 312 } |
295 } | 313 } |
OLD | NEW |