| 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 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 | 50 |
| 51 /// Whether multiple test files are being run. | 51 /// Whether multiple test files are being run. |
| 52 final bool _multiplePaths; | 52 final bool _multiplePaths; |
| 53 | 53 |
| 54 /// Whether tests are being run on multiple platforms. | 54 /// Whether tests are being run on multiple platforms. |
| 55 final bool _multiplePlatforms; | 55 final bool _multiplePlatforms; |
| 56 | 56 |
| 57 /// A stopwatch that tracks the duration of the full run. | 57 /// A stopwatch that tracks the duration of the full run. |
| 58 final _stopwatch = new Stopwatch(); | 58 final _stopwatch = new Stopwatch(); |
| 59 | 59 |
| 60 /// The set of tests that have completed and been marked as passing. | |
| 61 final _passed = new Set<LiveTest>(); | |
| 62 | |
| 63 /// The set of tests that have completed and been marked as skipped. | |
| 64 final _skipped = new Set<LiveTest>(); | |
| 65 | |
| 66 /// The set of tests that have completed and been marked as failing or error. | |
| 67 final _failed = new Set<LiveTest>(); | |
| 68 | |
| 69 /// The set of tests that are still running. | |
| 70 final _active = new List<LiveTest>(); | |
| 71 | |
| 72 /// Whether [close] has been called. | 60 /// Whether [close] has been called. |
| 73 bool _closed = false; | 61 bool _closed = false; |
| 74 | 62 |
| 75 /// The size of [_passed] last time a progress notification was printed. | 63 /// The size of `_engine.passed` last time a progress notification was |
| 64 /// printed. |
| 76 int _lastProgressPassed; | 65 int _lastProgressPassed; |
| 77 | 66 |
| 78 /// The size of [_skipped] last time a progress notification was printed. | 67 /// The size of `_engine.skipped` last time a progress notification was printe
d. |
| 79 int _lastProgressSkipped; | 68 int _lastProgressSkipped; |
| 80 | 69 |
| 81 /// The size of [_failed] last time a progress notification was printed. | 70 /// The size of `_engine.failed` last time a progress notification was |
| 71 /// printed. |
| 82 int _lastProgressFailed; | 72 int _lastProgressFailed; |
| 83 | 73 |
| 84 /// The message printed for the last progress notification. | 74 /// The message printed for the last progress notification. |
| 85 String _lastProgressMessage; | 75 String _lastProgressMessage; |
| 86 | 76 |
| 87 // Whether a newline has been printed since the last progress line. | 77 // Whether a newline has been printed since the last progress line. |
| 88 var _printedNewline = true; | 78 var _printedNewline = true; |
| 89 | 79 |
| 90 /// Creates a [ConsoleReporter] that will run all tests in [suites]. | 80 /// Creates a [ConsoleReporter] that will run all tests in [suites]. |
| 91 /// | 81 /// |
| 92 /// [concurrency] controls how many suites are run at once. If [color] is | 82 /// [concurrency] controls how many suites are run at once. If [color] is |
| 93 /// `true`, this will use terminal colors; if it's `false`, it won't. If | 83 /// `true`, this will use terminal colors; if it's `false`, it won't. If |
| 94 /// [verboseTrace] is `true`, this will print core library frames. | 84 /// [verboseTrace] is `true`, this will print core library frames. |
| 95 CompactReporter(Iterable<Suite> suites, {int concurrency, bool color: true, | 85 CompactReporter(Iterable<Suite> suites, {int concurrency, bool color: true, |
| 96 bool verboseTrace: false}) | 86 bool verboseTrace: false}) |
| 97 : _multiplePaths = suites.map((suite) => suite.path).toSet().length > 1, | 87 : _multiplePaths = suites.map((suite) => suite.path).toSet().length > 1, |
| 98 _multiplePlatforms = | 88 _multiplePlatforms = |
| 99 suites.map((suite) => suite.platform).toSet().length > 1, | 89 suites.map((suite) => suite.platform).toSet().length > 1, |
| 100 _engine = new Engine(suites, concurrency: concurrency), | 90 _engine = new Engine(suites, concurrency: concurrency), |
| 101 _verboseTrace = verboseTrace, | 91 _verboseTrace = verboseTrace, |
| 102 _color = color, | 92 _color = color, |
| 103 _green = color ? '\u001b[32m' : '', | 93 _green = color ? '\u001b[32m' : '', |
| 104 _red = color ? '\u001b[31m' : '', | 94 _red = color ? '\u001b[31m' : '', |
| 105 _yellow = color ? '\u001b[33m' : '', | 95 _yellow = color ? '\u001b[33m' : '', |
| 106 _noColor = color ? '\u001b[0m' : '' { | 96 _noColor = color ? '\u001b[0m' : '' { |
| 107 _engine.onTestStarted.listen((liveTest) { | 97 _engine.onTestStarted.listen((liveTest) { |
| 108 if (_active.isEmpty) _progressLine(_description(liveTest)); | 98 // If this is the first test to start, print a progress line so the user |
| 109 _active.add(liveTest); | 99 // knows what's running. |
| 100 if (_engine.active.length == 1) _progressLine(_description(liveTest)); |
| 110 _printedNewline = false; | 101 _printedNewline = false; |
| 111 | 102 |
| 112 liveTest.onStateChange.listen((state) { | 103 liveTest.onStateChange.listen((state) { |
| 113 if (state.status != Status.complete) return; | 104 if (state.status != Status.complete) return; |
| 114 _active.remove(liveTest); | |
| 115 | |
| 116 if (state.result != Result.success) { | |
| 117 _passed.remove(liveTest); | |
| 118 _failed.add(liveTest); | |
| 119 } else if (liveTest.test.metadata.skip) { | |
| 120 _skipped.add(liveTest); | |
| 121 } else { | |
| 122 _passed.add(liveTest); | |
| 123 } | |
| 124 | 105 |
| 125 if (liveTest.test.metadata.skip && | 106 if (liveTest.test.metadata.skip && |
| 126 liveTest.test.metadata.skipReason != null) { | 107 liveTest.test.metadata.skipReason != null) { |
| 127 _progressLine(_description(liveTest)); | 108 _progressLine(_description(liveTest)); |
| 128 print(''); | 109 print(''); |
| 129 print(indent('${_yellow}Skip: ${liveTest.test.metadata.skipReason}' | 110 print(indent('${_yellow}Skip: ${liveTest.test.metadata.skipReason}' |
| 130 '$_noColor')); | 111 '$_noColor')); |
| 131 } else { | 112 } else { |
| 132 // Always display the name of the oldest active test, unless testing | 113 // Always display the name of the oldest active test, unless testing |
| 133 // is finished in which case display the last test to complete. | 114 // is finished in which case display the last test to complete. |
| 134 if (_active.isEmpty) { | 115 if (_engine.active.isEmpty) { |
| 135 _progressLine(_description(liveTest)); | 116 _progressLine(_description(liveTest)); |
| 136 } else { | 117 } else { |
| 137 _progressLine(_description(_active.first)); | 118 _progressLine(_description(_engine.active.first)); |
| 138 } | 119 } |
| 139 | 120 |
| 140 _printedNewline = false; | 121 _printedNewline = false; |
| 141 } | 122 } |
| 142 }); | 123 }); |
| 143 | 124 |
| 144 liveTest.onError.listen((error) { | 125 liveTest.onError.listen((error) { |
| 145 if (liveTest.state.status != Status.complete) return; | 126 if (liveTest.state.status != Status.complete) return; |
| 146 | 127 |
| 147 _progressLine(_description(liveTest)); | 128 _progressLine(_description(liveTest)); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 return true; | 172 return true; |
| 192 } | 173 } |
| 193 | 174 |
| 194 _stopwatch.start(); | 175 _stopwatch.start(); |
| 195 var success = await _engine.run(); | 176 var success = await _engine.run(); |
| 196 if (_closed) return false; | 177 if (_closed) return false; |
| 197 | 178 |
| 198 if (!success) { | 179 if (!success) { |
| 199 _progressLine('Some tests failed.', color: _red); | 180 _progressLine('Some tests failed.', color: _red); |
| 200 print(''); | 181 print(''); |
| 201 } else if (_passed.isEmpty) { | 182 } else if (_engine.passed.isEmpty) { |
| 202 _progressLine("All tests skipped."); | 183 _progressLine("All tests skipped."); |
| 203 print(''); | 184 print(''); |
| 204 } else { | 185 } else { |
| 205 _progressLine("All tests passed!"); | 186 _progressLine("All tests passed!"); |
| 206 print(''); | 187 print(''); |
| 207 } | 188 } |
| 208 | 189 |
| 209 return success; | 190 return success; |
| 210 } | 191 } |
| 211 | 192 |
| 212 /// Signals that the caller is done with any test output and the reporter | 193 /// Signals that the caller is done with any test output and the reporter |
| 213 /// should release any resources it has allocated. | 194 /// should release any resources it has allocated. |
| 214 Future close() { | 195 Future close() { |
| 215 if (!_printedNewline) print(""); | 196 if (!_printedNewline) print(""); |
| 216 _printedNewline = true; | 197 _printedNewline = true; |
| 217 _closed = true; | 198 _closed = true; |
| 218 return _engine.close(); | 199 return _engine.close(); |
| 219 } | 200 } |
| 220 | 201 |
| 221 /// Prints a line representing the current state of the tests. | 202 /// Prints a line representing the current state of the tests. |
| 222 /// | 203 /// |
| 223 /// [message] goes after the progress report, and may be truncated to fit the | 204 /// [message] goes after the progress report, and may be truncated to fit the |
| 224 /// entire line within [_lineLength]. If [color] is passed, it's used as the | 205 /// entire line within [_lineLength]. If [color] is passed, it's used as the |
| 225 /// color for [message]. | 206 /// color for [message]. |
| 226 bool _progressLine(String message, {String color}) { | 207 bool _progressLine(String message, {String color}) { |
| 227 // Print nothing if nothing has changed since the last progress line. | 208 // Print nothing if nothing has changed since the last progress line. |
| 228 if (_passed.length == _lastProgressPassed && | 209 if (_engine.passed.length == _lastProgressPassed && |
| 229 _skipped.length == _lastProgressSkipped && | 210 _engine.skipped.length == _lastProgressSkipped && |
| 230 _failed.length == _lastProgressFailed && | 211 _engine.failed.length == _lastProgressFailed && |
| 231 message == _lastProgressMessage) { | 212 message == _lastProgressMessage) { |
| 232 return false; | 213 return false; |
| 233 } | 214 } |
| 234 | 215 |
| 235 _lastProgressPassed = _passed.length; | 216 _lastProgressPassed = _engine.passed.length; |
| 236 _lastProgressSkipped = _skipped.length; | 217 _lastProgressSkipped = _engine.skipped.length; |
| 237 _lastProgressFailed = _failed.length; | 218 _lastProgressFailed = _engine.failed.length; |
| 238 _lastProgressMessage = message; | 219 _lastProgressMessage = message; |
| 239 | 220 |
| 240 if (color == null) color = ''; | 221 if (color == null) color = ''; |
| 241 var duration = _stopwatch.elapsed; | 222 var duration = _stopwatch.elapsed; |
| 242 var buffer = new StringBuffer(); | 223 var buffer = new StringBuffer(); |
| 243 | 224 |
| 244 // \r moves back to the beginning of the current line. | 225 // \r moves back to the beginning of the current line. |
| 245 buffer.write('\r${_timeString(duration)} '); | 226 buffer.write('\r${_timeString(duration)} '); |
| 246 buffer.write(_green); | 227 buffer.write(_green); |
| 247 buffer.write('+'); | 228 buffer.write('+'); |
| 248 buffer.write(_passed.length); | 229 buffer.write(_engine.passed.length); |
| 249 buffer.write(_noColor); | 230 buffer.write(_noColor); |
| 250 | 231 |
| 251 if (_skipped.isNotEmpty) { | 232 if (_engine.skipped.isNotEmpty) { |
| 252 buffer.write(_yellow); | 233 buffer.write(_yellow); |
| 253 buffer.write(' ~'); | 234 buffer.write(' ~'); |
| 254 buffer.write(_skipped.length); | 235 buffer.write(_engine.skipped.length); |
| 255 buffer.write(_noColor); | 236 buffer.write(_noColor); |
| 256 } | 237 } |
| 257 | 238 |
| 258 if (_failed.isNotEmpty) { | 239 if (_engine.failed.isNotEmpty) { |
| 259 buffer.write(_red); | 240 buffer.write(_red); |
| 260 buffer.write(' -'); | 241 buffer.write(' -'); |
| 261 buffer.write(_failed.length); | 242 buffer.write(_engine.failed.length); |
| 262 buffer.write(_noColor); | 243 buffer.write(_noColor); |
| 263 } | 244 } |
| 264 | 245 |
| 265 buffer.write(': '); | 246 buffer.write(': '); |
| 266 buffer.write(color); | 247 buffer.write(color); |
| 267 | 248 |
| 268 // Ensure the line fits within [_lineLength]. [buffer] includes the color | 249 // Ensure the line fits within [_lineLength]. [buffer] includes the color |
| 269 // escape sequences too. Because these sequences are not visible characters, | 250 // escape sequences too. Because these sequences are not visible characters, |
| 270 // we make sure they are not counted towards the limit. | 251 // we make sure they are not counted towards the limit. |
| 271 var nonVisible = 1 + _green.length + _noColor.length + color.length + | 252 var nonVisible = 1 + _green.length + _noColor.length + color.length + |
| 272 (_failed.isEmpty ? 0 : _red.length + _noColor.length); | 253 (_engine.failed.isEmpty ? 0 : _red.length + _noColor.length); |
| 273 var length = buffer.length - nonVisible; | 254 var length = buffer.length - nonVisible; |
| 274 buffer.write(truncate(message, _lineLength - length)); | 255 buffer.write(truncate(message, _lineLength - length)); |
| 275 buffer.write(_noColor); | 256 buffer.write(_noColor); |
| 276 | 257 |
| 277 // Pad the rest of the line so that it looks erased. | 258 // Pad the rest of the line so that it looks erased. |
| 278 length = buffer.length - nonVisible - _noColor.length; | 259 length = buffer.length - nonVisible - _noColor.length; |
| 279 buffer.write(' ' * (_lineLength - length)); | 260 buffer.write(' ' * (_lineLength - length)); |
| 280 stdout.write(buffer.toString()); | 261 stdout.write(buffer.toString()); |
| 281 return true; | 262 return true; |
| 282 } | 263 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 298 name = "${liveTest.suite.path}: $name"; | 279 name = "${liveTest.suite.path}: $name"; |
| 299 } | 280 } |
| 300 | 281 |
| 301 if (_multiplePlatforms && liveTest.suite.platform != null) { | 282 if (_multiplePlatforms && liveTest.suite.platform != null) { |
| 302 name = "[${liveTest.suite.platform}] $name"; | 283 name = "[${liveTest.suite.platform}] $name"; |
| 303 } | 284 } |
| 304 | 285 |
| 305 return name; | 286 return name; |
| 306 } | 287 } |
| 307 } | 288 } |
| OLD | NEW |