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:async'; | 7 import 'dart:async'; |
8 import 'dart:io'; | 8 import 'dart:io'; |
9 import 'dart:isolate'; | 9 import 'dart:isolate'; |
10 | 10 |
11 import '../../backend/live_test.dart'; | 11 import '../../backend/live_test.dart'; |
12 import '../../backend/state.dart'; | 12 import '../../backend/state.dart'; |
13 import '../../utils.dart'; | 13 import '../../utils.dart'; |
| 14 import '../../utils.dart' as utils; |
14 import '../engine.dart'; | 15 import '../engine.dart'; |
15 import '../load_exception.dart'; | 16 import '../load_exception.dart'; |
16 import '../load_suite.dart'; | 17 import '../load_suite.dart'; |
17 | 18 |
18 /// The maximum console line length. | 19 /// The maximum console line length. |
19 /// | 20 /// |
20 /// Lines longer than this will be cropped. | 21 /// Lines longer than this will be cropped. |
21 const _lineLength = 100; | 22 const _lineLength = 100; |
22 | 23 |
23 /// A reporter that prints test results to the console in a single | 24 /// A reporter that prints test results to the console in a single |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 /// printed. | 80 /// printed. |
80 int _lastProgressFailed; | 81 int _lastProgressFailed; |
81 | 82 |
82 /// The duration of the test run in seconds last time a progress notification | 83 /// The duration of the test run in seconds last time a progress notification |
83 /// was printed. | 84 /// was printed. |
84 int _lastProgressElapsed; | 85 int _lastProgressElapsed; |
85 | 86 |
86 /// The message printed for the last progress notification. | 87 /// The message printed for the last progress notification. |
87 String _lastProgressMessage; | 88 String _lastProgressMessage; |
88 | 89 |
| 90 /// Whether the message printed for the last progress notification was |
| 91 /// truncated. |
| 92 bool _lastProgressTruncated; |
| 93 |
89 // Whether a newline has been printed since the last progress line. | 94 // Whether a newline has been printed since the last progress line. |
90 var _printedNewline = true; | 95 var _printedNewline = true; |
91 | 96 |
92 /// Watches the tests run by [engine] and prints their results to the | 97 /// Watches the tests run by [engine] and prints their results to the |
93 /// terminal. | 98 /// terminal. |
94 /// | 99 /// |
95 /// If [color] is `true`, this will use terminal colors; if it's `false`, it | 100 /// If [color] is `true`, this will use terminal colors; if it's `false`, it |
96 /// won't. If [verboseTrace] is `true`, this will print core library frames. | 101 /// won't. If [verboseTrace] is `true`, this will print core library frames. |
97 /// If [printPath] is `true`, this will print the path name as part of the | 102 /// If [printPath] is `true`, this will print the path name as part of the |
98 /// test description. Likewise, if [printPlatform] is `true`, this will print | 103 /// test description. Likewise, if [printPlatform] is `true`, this will print |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 _timer = new Timer.periodic(new Duration(seconds: 1), | 136 _timer = new Timer.periodic(new Duration(seconds: 1), |
132 (_) => _progressLine(_lastProgressMessage)); | 137 (_) => _progressLine(_lastProgressMessage)); |
133 } | 138 } |
134 | 139 |
135 // If this is the first test to start, print a progress line so the user | 140 // If this is the first test to start, print a progress line so the user |
136 // knows what's running. It's possible that the active test may not be | 141 // knows what's running. It's possible that the active test may not be |
137 // [liveTest] because the engine doesn't always surface load tests. | 142 // [liveTest] because the engine doesn't always surface load tests. |
138 if (_engine.active.length == 1 && _engine.active.first == liveTest) { | 143 if (_engine.active.length == 1 && _engine.active.first == liveTest) { |
139 _progressLine(_description(liveTest)); | 144 _progressLine(_description(liveTest)); |
140 } | 145 } |
141 _printedNewline = false; | |
142 | 146 |
143 liveTest.onStateChange.listen((state) => _onStateChange(liveTest, state)); | 147 liveTest.onStateChange.listen((state) => _onStateChange(liveTest, state)); |
144 | 148 |
145 liveTest.onError.listen((error) => | 149 liveTest.onError.listen((error) => |
146 _onError(liveTest, error.error, error.stackTrace)); | 150 _onError(liveTest, error.error, error.stackTrace)); |
147 | 151 |
148 liveTest.onPrint.listen((line) { | 152 liveTest.onPrint.listen((line) { |
149 _progressLine(_description(liveTest)); | 153 _progressLine(_description(liveTest), truncate: false); |
150 if (!_printedNewline) print(''); | 154 if (!_printedNewline) print(''); |
151 _printedNewline = true; | 155 _printedNewline = true; |
152 | 156 |
153 print(line); | 157 print(line); |
154 }); | 158 }); |
155 } | 159 } |
156 | 160 |
157 /// A callback called when [liveTest]'s state becomes [state]. | 161 /// A callback called when [liveTest]'s state becomes [state]. |
158 void _onStateChange(LiveTest liveTest, State state) { | 162 void _onStateChange(LiveTest liveTest, State state) { |
159 if (state.status != Status.complete) return; | 163 if (state.status != Status.complete) return; |
160 | 164 |
161 if (liveTest.test.metadata.skip && | 165 if (liveTest.test.metadata.skip && |
162 liveTest.test.metadata.skipReason != null) { | 166 liveTest.test.metadata.skipReason != null) { |
163 _progressLine(_description(liveTest)); | 167 _progressLine(_description(liveTest)); |
164 print(''); | 168 print(''); |
165 print(indent('${_yellow}Skip: ${liveTest.test.metadata.skipReason}' | 169 print(indent('${_yellow}Skip: ${liveTest.test.metadata.skipReason}' |
166 '$_noColor')); | 170 '$_noColor')); |
167 } else { | 171 } else { |
168 // Always display the name of the oldest active test, unless testing | 172 // Always display the name of the oldest active test, unless testing |
169 // is finished in which case display the last test to complete. | 173 // is finished in which case display the last test to complete. |
170 if (_engine.active.isEmpty) { | 174 if (_engine.active.isEmpty) { |
171 _progressLine(_description(liveTest)); | 175 _progressLine(_description(liveTest)); |
172 } else { | 176 } else { |
173 _progressLine(_description(_engine.active.first)); | 177 _progressLine(_description(_engine.active.first)); |
174 } | 178 } |
175 | |
176 _printedNewline = false; | |
177 } | 179 } |
178 } | 180 } |
179 | 181 |
180 /// A callback called when [liveTest] throws [error]. | 182 /// A callback called when [liveTest] throws [error]. |
181 void _onError(LiveTest liveTest, error, StackTrace stackTrace) { | 183 void _onError(LiveTest liveTest, error, StackTrace stackTrace) { |
182 if (liveTest.state.status != Status.complete) return; | 184 if (liveTest.state.status != Status.complete) return; |
183 | 185 |
184 _progressLine(_description(liveTest)); | 186 _progressLine(_description(liveTest), truncate: false); |
185 if (!_printedNewline) print(''); | 187 if (!_printedNewline) print(''); |
186 _printedNewline = true; | 188 _printedNewline = true; |
187 | 189 |
188 if (error is! LoadException) { | 190 if (error is! LoadException) { |
189 print(indent(error.toString())); | 191 print(indent(error.toString())); |
190 var chain = terseChain(stackTrace, verbose: _verboseTrace); | 192 var chain = terseChain(stackTrace, verbose: _verboseTrace); |
191 print(indent(chain.toString())); | 193 print(indent(chain.toString())); |
192 return; | 194 return; |
193 } | 195 } |
194 | 196 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 _progressLine("All tests passed!"); | 242 _progressLine("All tests passed!"); |
241 print(''); | 243 print(''); |
242 } | 244 } |
243 } | 245 } |
244 | 246 |
245 /// Prints a line representing the current state of the tests. | 247 /// Prints a line representing the current state of the tests. |
246 /// | 248 /// |
247 /// [message] goes after the progress report, and may be truncated to fit the | 249 /// [message] goes after the progress report, and may be truncated to fit the |
248 /// entire line within [_lineLength]. If [color] is passed, it's used as the | 250 /// entire line within [_lineLength]. If [color] is passed, it's used as the |
249 /// color for [message]. | 251 /// color for [message]. |
250 bool _progressLine(String message, {String color}) { | 252 bool _progressLine(String message, {String color, bool truncate: true}) { |
251 var elapsed = _stopwatch.elapsed.inSeconds; | 253 var elapsed = _stopwatch.elapsed.inSeconds; |
252 | 254 |
253 // Print nothing if nothing has changed since the last progress line. | 255 // Print nothing if nothing has changed since the last progress line. |
254 if (_engine.passed.length == _lastProgressPassed && | 256 if (_engine.passed.length == _lastProgressPassed && |
255 _engine.skipped.length == _lastProgressSkipped && | 257 _engine.skipped.length == _lastProgressSkipped && |
256 _engine.failed.length == _lastProgressFailed && | 258 _engine.failed.length == _lastProgressFailed && |
257 elapsed == _lastProgressElapsed && | 259 elapsed == _lastProgressElapsed && |
258 message == _lastProgressMessage) { | 260 message == _lastProgressMessage && |
| 261 truncate == _lastProgressTruncated) { |
259 return false; | 262 return false; |
260 } | 263 } |
261 | 264 |
262 _lastProgressPassed = _engine.passed.length; | 265 _lastProgressPassed = _engine.passed.length; |
263 _lastProgressSkipped = _engine.skipped.length; | 266 _lastProgressSkipped = _engine.skipped.length; |
264 _lastProgressFailed = _engine.failed.length; | 267 _lastProgressFailed = _engine.failed.length; |
265 _lastProgressElapsed = elapsed; | 268 _lastProgressElapsed = elapsed; |
266 _lastProgressMessage = message; | 269 _lastProgressMessage = message; |
| 270 _lastProgressTruncated = truncate; |
267 | 271 |
268 if (color == null) color = ''; | 272 if (color == null) color = ''; |
269 var duration = _stopwatch.elapsed; | 273 var duration = _stopwatch.elapsed; |
270 var buffer = new StringBuffer(); | 274 var buffer = new StringBuffer(); |
271 | 275 |
272 // \r moves back to the beginning of the current line. | 276 // \r moves back to the beginning of the current line. |
273 buffer.write('\r${_timeString(duration)} '); | 277 buffer.write('\r${_timeString(duration)} '); |
274 buffer.write(_green); | 278 buffer.write(_green); |
275 buffer.write('+'); | 279 buffer.write('+'); |
276 buffer.write(_engine.passed.length); | 280 buffer.write(_engine.passed.length); |
(...skipping 13 matching lines...) Expand all Loading... |
290 buffer.write(_noColor); | 294 buffer.write(_noColor); |
291 } | 295 } |
292 | 296 |
293 buffer.write(': '); | 297 buffer.write(': '); |
294 buffer.write(color); | 298 buffer.write(color); |
295 | 299 |
296 // Ensure the line fits within [_lineLength]. [buffer] includes the color | 300 // Ensure the line fits within [_lineLength]. [buffer] includes the color |
297 // escape sequences too. Because these sequences are not visible characters, | 301 // escape sequences too. Because these sequences are not visible characters, |
298 // we make sure they are not counted towards the limit. | 302 // we make sure they are not counted towards the limit. |
299 var length = withoutColors(buffer.toString()).length; | 303 var length = withoutColors(buffer.toString()).length; |
300 buffer.write(truncate(message, _lineLength - length)); | 304 if (truncate) message = utils.truncate(message, _lineLength - length); |
| 305 buffer.write(message); |
301 buffer.write(_noColor); | 306 buffer.write(_noColor); |
302 | 307 |
303 // Pad the rest of the line so that it looks erased. | 308 // Pad the rest of the line so that it looks erased. |
304 buffer.write(' ' * (_lineLength - withoutColors(buffer.toString()).length)); | 309 buffer.write(' ' * (_lineLength - withoutColors(buffer.toString()).length)); |
305 stdout.write(buffer.toString()); | 310 stdout.write(buffer.toString()); |
| 311 |
| 312 _printedNewline = false; |
306 return true; | 313 return true; |
307 } | 314 } |
308 | 315 |
309 /// Returns a representation of [duration] as `MM:SS`. | 316 /// Returns a representation of [duration] as `MM:SS`. |
310 String _timeString(Duration duration) { | 317 String _timeString(Duration duration) { |
311 return "${duration.inMinutes.toString().padLeft(2, '0')}:" | 318 return "${duration.inMinutes.toString().padLeft(2, '0')}:" |
312 "${(duration.inSeconds % 60).toString().padLeft(2, '0')}"; | 319 "${(duration.inSeconds % 60).toString().padLeft(2, '0')}"; |
313 } | 320 } |
314 | 321 |
315 /// Returns a description of [liveTest]. | 322 /// Returns a description of [liveTest]. |
316 /// | 323 /// |
317 /// This differs from the test's own description in that it may also include | 324 /// This differs from the test's own description in that it may also include |
318 /// the suite's name. | 325 /// the suite's name. |
319 String _description(LiveTest liveTest) { | 326 String _description(LiveTest liveTest) { |
320 var name = liveTest.test.name; | 327 var name = liveTest.test.name; |
321 | 328 |
322 if (_printPath && liveTest.suite.path != null) { | 329 if (_printPath && liveTest.suite.path != null) { |
323 name = "${liveTest.suite.path}: $name"; | 330 name = "${liveTest.suite.path}: $name"; |
324 } | 331 } |
325 | 332 |
326 if (_printPlatform && liveTest.suite.platform != null) { | 333 if (_printPlatform && liveTest.suite.platform != null) { |
327 name = "[${liveTest.suite.platform}] $name"; | 334 name = "[${liveTest.suite.platform}] $name"; |
328 } | 335 } |
329 | 336 |
330 if (liveTest.suite is LoadSuite) name = "$_bold$_gray$name$_noColor"; | 337 if (liveTest.suite is LoadSuite) name = "$_bold$_gray$name$_noColor"; |
331 | 338 |
332 return name; | 339 return name; |
333 } | 340 } |
334 } | 341 } |
OLD | NEW |