| 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 16 matching lines...) Expand all Loading... |
| 27 final bool _color; | 27 final bool _color; |
| 28 | 28 |
| 29 /// The terminal escape for green text, or the empty string if this is Windows | 29 /// The terminal escape for green text, or the empty string if this is Windows |
| 30 /// or not outputting to a terminal. | 30 /// or not outputting to a terminal. |
| 31 final String _green; | 31 final String _green; |
| 32 | 32 |
| 33 /// The terminal escape for red text, or the empty string if this is Windows | 33 /// The terminal escape for red text, or the empty string if this is Windows |
| 34 /// or not outputting to a terminal. | 34 /// or not outputting to a terminal. |
| 35 final String _red; | 35 final String _red; |
| 36 | 36 |
| 37 /// The terminal escape for yellow text, or the empty string if this is |
| 38 /// Windows or not outputting to a terminal. |
| 39 final String _yellow; |
| 40 |
| 37 /// The terminal escape for removing test coloring, or the empty string if | 41 /// The terminal escape for removing test coloring, or the empty string if |
| 38 /// this is Windows or not outputting to a terminal. | 42 /// this is Windows or not outputting to a terminal. |
| 39 final String _noColor; | 43 final String _noColor; |
| 40 | 44 |
| 41 /// The engine used to run the tests. | 45 /// The engine used to run the tests. |
| 42 final Engine _engine; | 46 final Engine _engine; |
| 43 | 47 |
| 44 /// Whether multiple test files are being run. | 48 /// Whether multiple test files are being run. |
| 45 final bool _multiplePaths; | 49 final bool _multiplePaths; |
| 46 | 50 |
| 47 /// Whether tests are being run on multiple platforms. | 51 /// Whether tests are being run on multiple platforms. |
| 48 final bool _multiplePlatforms; | 52 final bool _multiplePlatforms; |
| 49 | 53 |
| 50 /// A stopwatch that tracks the duration of the full run. | 54 /// A stopwatch that tracks the duration of the full run. |
| 51 final _stopwatch = new Stopwatch(); | 55 final _stopwatch = new Stopwatch(); |
| 52 | 56 |
| 53 /// The set of tests that have completed and been marked as passing. | 57 /// The set of tests that have completed and been marked as passing. |
| 54 final _passed = new Set<LiveTest>(); | 58 final _passed = new Set<LiveTest>(); |
| 55 | 59 |
| 60 /// The set of tests that have completed and been marked as skipped. |
| 61 final _skipped = new Set<LiveTest>(); |
| 62 |
| 56 /// The set of tests that have completed and been marked as failing or error. | 63 /// The set of tests that have completed and been marked as failing or error. |
| 57 final _failed = new Set<LiveTest>(); | 64 final _failed = new Set<LiveTest>(); |
| 58 | 65 |
| 59 /// The set of tests that are still running. | 66 /// The set of tests that are still running. |
| 60 final _active = new List<LiveTest>(); | 67 final _active = new List<LiveTest>(); |
| 61 | 68 |
| 62 /// Whether [close] has been called. | 69 /// Whether [close] has been called. |
| 63 bool _closed = false; | 70 bool _closed = false; |
| 64 | 71 |
| 65 /// The size of [_passed] last time a progress notification was printed. | 72 /// The size of [_passed] last time a progress notification was printed. |
| 66 int _lastProgressPassed; | 73 int _lastProgressPassed; |
| 67 | 74 |
| 75 /// The size of [_skipped] last time a progress notification was printed. |
| 76 int _lastProgressSkipped; |
| 77 |
| 68 /// The size of [_failed] last time a progress notification was printed. | 78 /// The size of [_failed] last time a progress notification was printed. |
| 69 int _lastProgressFailed; | 79 int _lastProgressFailed; |
| 70 | 80 |
| 71 /// The message printed for the last progress notification. | 81 /// The message printed for the last progress notification. |
| 72 String _lastProgressMessage; | 82 String _lastProgressMessage; |
| 73 | 83 |
| 74 // Whether a newline has been printed since the last progress line. | 84 // Whether a newline has been printed since the last progress line. |
| 75 var _printedNewline = true; | 85 var _printedNewline = true; |
| 76 | 86 |
| 77 /// Creates a [ConsoleReporter] that will run all tests in [suites]. | 87 /// Creates a [ConsoleReporter] that will run all tests in [suites]. |
| 78 /// | 88 /// |
| 79 /// If [color] is `true`, this will use terminal colors; if it's `false`, it | 89 /// If [color] is `true`, this will use terminal colors; if it's `false`, it |
| 80 /// won't. | 90 /// won't. |
| 81 CompactReporter(Iterable<Suite> suites, {int concurrency, bool color: true}) | 91 CompactReporter(Iterable<Suite> suites, {int concurrency, bool color: true}) |
| 82 : _multiplePaths = suites.map((suite) => suite.path).toSet().length > 1, | 92 : _multiplePaths = suites.map((suite) => suite.path).toSet().length > 1, |
| 83 _multiplePlatforms = | 93 _multiplePlatforms = |
| 84 suites.map((suite) => suite.platform).toSet().length > 1, | 94 suites.map((suite) => suite.platform).toSet().length > 1, |
| 85 _engine = new Engine(suites, concurrency: concurrency), | 95 _engine = new Engine(suites, concurrency: concurrency), |
| 86 _color = color, | 96 _color = color, |
| 87 _green = color ? '\u001b[32m' : '', | 97 _green = color ? '\u001b[32m' : '', |
| 88 _red = color ? '\u001b[31m' : '', | 98 _red = color ? '\u001b[31m' : '', |
| 99 _yellow = color ? '\u001b[33m' : '', |
| 89 _noColor = color ? '\u001b[0m' : '' { | 100 _noColor = color ? '\u001b[0m' : '' { |
| 90 _engine.onTestStarted.listen((liveTest) { | 101 _engine.onTestStarted.listen((liveTest) { |
| 91 if (_active.isEmpty) _progressLine(_description(liveTest)); | 102 if (_active.isEmpty) _progressLine(_description(liveTest)); |
| 92 _active.add(liveTest); | 103 _active.add(liveTest); |
| 93 _printedNewline = false; | 104 _printedNewline = false; |
| 94 | 105 |
| 95 liveTest.onStateChange.listen((state) { | 106 liveTest.onStateChange.listen((state) { |
| 96 if (state.status != Status.complete) return; | 107 if (state.status != Status.complete) return; |
| 97 _active.remove(liveTest); | 108 _active.remove(liveTest); |
| 98 if (state.result == Result.success) { | 109 |
| 99 _passed.add(liveTest); | 110 if (state.result != Result.success) { |
| 100 } else { | |
| 101 _passed.remove(liveTest); | 111 _passed.remove(liveTest); |
| 102 _failed.add(liveTest); | 112 _failed.add(liveTest); |
| 113 } else if (liveTest.test.metadata.skip) { |
| 114 _skipped.add(liveTest); |
| 115 } else { |
| 116 _passed.add(liveTest); |
| 103 } | 117 } |
| 104 | 118 |
| 105 // Always display the name of the oldest active test, unless testing is | 119 // Always display the name of the oldest active test, unless testing is |
| 106 // finished in which case display the last test to complete. | 120 // finished in which case display the last test to complete. |
| 107 if (_active.isEmpty) { | 121 if (_active.isEmpty) { |
| 108 _progressLine(_description(liveTest)); | 122 _progressLine(_description(liveTest)); |
| 109 } else { | 123 } else { |
| 110 _progressLine(_description(_active.first)); | 124 _progressLine(_description(_active.first)); |
| 111 } | 125 } |
| 112 | 126 |
| 113 _printedNewline = false; | 127 if (liveTest.test.metadata.skip && |
| 128 liveTest.test.metadata.skipReason != null) { |
| 129 print(''); |
| 130 print(indent('${_yellow}Skip: ${liveTest.test.metadata.skipReason}' |
| 131 '$_noColor')); |
| 132 } else { |
| 133 _printedNewline = false; |
| 134 } |
| 114 }); | 135 }); |
| 115 | 136 |
| 116 liveTest.onError.listen((error) { | 137 liveTest.onError.listen((error) { |
| 117 if (liveTest.state.status != Status.complete) return; | 138 if (liveTest.state.status != Status.complete) return; |
| 118 | 139 |
| 119 _progressLine(_description(liveTest)); | 140 _progressLine(_description(liveTest)); |
| 120 if (!_printedNewline) print(''); | 141 if (!_printedNewline) print(''); |
| 121 _printedNewline = true; | 142 _printedNewline = true; |
| 122 | 143 |
| 123 if (error.error is! LoadException) { | 144 if (error.error is! LoadException) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 | 180 |
| 160 if (_engine.liveTests.isEmpty) { | 181 if (_engine.liveTests.isEmpty) { |
| 161 print("No tests ran."); | 182 print("No tests ran."); |
| 162 return new Future.value(true); | 183 return new Future.value(true); |
| 163 } | 184 } |
| 164 | 185 |
| 165 _stopwatch.start(); | 186 _stopwatch.start(); |
| 166 return _engine.run().then((success) { | 187 return _engine.run().then((success) { |
| 167 if (_closed) return false; | 188 if (_closed) return false; |
| 168 | 189 |
| 169 if (success) { | 190 if (!success) { |
| 170 _progressLine("All tests passed!"); | 191 _progressLine('Some tests failed.', color: _red); |
| 192 print(''); |
| 193 } else if (_passed.isEmpty) { |
| 194 _progressLine("All tests skipped."); |
| 171 print(''); | 195 print(''); |
| 172 } else { | 196 } else { |
| 173 _progressLine('Some tests failed.', color: _red); | 197 _progressLine("All tests passed!"); |
| 174 print(''); | 198 print(''); |
| 175 } | 199 } |
| 176 | 200 |
| 177 return success; | 201 return success; |
| 178 }); | 202 }); |
| 179 } | 203 } |
| 180 | 204 |
| 181 /// Signals that the caller is done with any test output and the reporter | 205 /// Signals that the caller is done with any test output and the reporter |
| 182 /// should release any resources it has allocated. | 206 /// should release any resources it has allocated. |
| 183 Future close() { | 207 Future close() { |
| 184 if (!_printedNewline) print(""); | 208 if (!_printedNewline) print(""); |
| 185 _printedNewline = true; | 209 _printedNewline = true; |
| 186 _closed = true; | 210 _closed = true; |
| 187 return _engine.close(); | 211 return _engine.close(); |
| 188 } | 212 } |
| 189 | 213 |
| 190 /// Prints a line representing the current state of the tests. | 214 /// Prints a line representing the current state of the tests. |
| 191 /// | 215 /// |
| 192 /// [message] goes after the progress report, and may be truncated to fit the | 216 /// [message] goes after the progress report, and may be truncated to fit the |
| 193 /// entire line within [_lineLength]. If [color] is passed, it's used as the | 217 /// entire line within [_lineLength]. If [color] is passed, it's used as the |
| 194 /// color for [message]. | 218 /// color for [message]. |
| 195 bool _progressLine(String message, {String color}) { | 219 bool _progressLine(String message, {String color}) { |
| 196 // Print nothing if nothing has changed since the last progress line. | 220 // Print nothing if nothing has changed since the last progress line. |
| 197 if (_passed.length == _lastProgressPassed && | 221 if (_passed.length == _lastProgressPassed && |
| 222 _skipped.length == _lastProgressSkipped && |
| 198 _failed.length == _lastProgressFailed && | 223 _failed.length == _lastProgressFailed && |
| 199 message == _lastProgressMessage) { | 224 message == _lastProgressMessage) { |
| 200 return false; | 225 return false; |
| 201 } | 226 } |
| 202 | 227 |
| 203 _lastProgressPassed = _passed.length; | 228 _lastProgressPassed = _passed.length; |
| 229 _lastProgressSkipped = _skipped.length; |
| 204 _lastProgressFailed = _failed.length; | 230 _lastProgressFailed = _failed.length; |
| 205 _lastProgressMessage = message; | 231 _lastProgressMessage = message; |
| 206 | 232 |
| 207 if (color == null) color = ''; | 233 if (color == null) color = ''; |
| 208 var duration = _stopwatch.elapsed; | 234 var duration = _stopwatch.elapsed; |
| 209 var buffer = new StringBuffer(); | 235 var buffer = new StringBuffer(); |
| 210 | 236 |
| 211 // \r moves back to the beginning of the current line. | 237 // \r moves back to the beginning of the current line. |
| 212 buffer.write('\r${_timeString(duration)} '); | 238 buffer.write('\r${_timeString(duration)} '); |
| 213 buffer.write(_green); | 239 buffer.write(_green); |
| 214 buffer.write('+'); | 240 buffer.write('+'); |
| 215 buffer.write(_passed.length); | 241 buffer.write(_passed.length); |
| 216 buffer.write(_noColor); | 242 buffer.write(_noColor); |
| 217 | 243 |
| 244 if (_skipped.isNotEmpty) { |
| 245 buffer.write(_yellow); |
| 246 buffer.write(' ~'); |
| 247 buffer.write(_skipped.length); |
| 248 buffer.write(_noColor); |
| 249 } |
| 250 |
| 218 if (_failed.isNotEmpty) { | 251 if (_failed.isNotEmpty) { |
| 219 buffer.write(_red); | 252 buffer.write(_red); |
| 220 buffer.write(' -'); | 253 buffer.write(' -'); |
| 221 buffer.write(_failed.length); | 254 buffer.write(_failed.length); |
| 222 buffer.write(_noColor); | 255 buffer.write(_noColor); |
| 223 } | 256 } |
| 224 | 257 |
| 225 buffer.write(': '); | 258 buffer.write(': '); |
| 226 buffer.write(color); | 259 buffer.write(color); |
| 227 | 260 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 258 name = "${liveTest.suite.path}: $name"; | 291 name = "${liveTest.suite.path}: $name"; |
| 259 } | 292 } |
| 260 | 293 |
| 261 if (_multiplePlatforms && liveTest.suite.platform != null) { | 294 if (_multiplePlatforms && liveTest.suite.platform != null) { |
| 262 name = "[${liveTest.suite.platform}] $name"; | 295 name = "[${liveTest.suite.platform}] $name"; |
| 263 } | 296 } |
| 264 | 297 |
| 265 return name; | 298 return name; |
| 266 } | 299 } |
| 267 } | 300 } |
| OLD | NEW |