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 unittest.console_reporter; | 5 library unittest.console_reporter; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:io'; | 8 import 'dart:io'; |
9 | 9 |
10 import 'engine.dart'; | 10 import 'engine.dart'; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 | 42 |
43 /// A stopwatch that tracks the duration of the full run. | 43 /// A stopwatch that tracks the duration of the full run. |
44 final _stopwatch = new Stopwatch(); | 44 final _stopwatch = new Stopwatch(); |
45 | 45 |
46 /// The set of tests that have completed and been marked as passing. | 46 /// The set of tests that have completed and been marked as passing. |
47 final _passed = new Set<LiveTest>(); | 47 final _passed = new Set<LiveTest>(); |
48 | 48 |
49 /// The set of tests that have completed and been marked as failing or error. | 49 /// The set of tests that have completed and been marked as failing or error. |
50 final _failed = new Set<LiveTest>(); | 50 final _failed = new Set<LiveTest>(); |
51 | 51 |
| 52 /// The size of [_passed] last time a progress notification was printed. |
| 53 int _lastProgressPassed; |
| 54 |
| 55 /// The size of [_failed] last time a progress notification was printed. |
| 56 int _lastProgressFailed; |
| 57 |
| 58 /// The message printed for the last progress notification. |
| 59 String _lastProgressMessage; |
| 60 |
52 /// Creates a [ConsoleReporter] that will run all tests in [suites]. | 61 /// Creates a [ConsoleReporter] that will run all tests in [suites]. |
53 ConsoleReporter(Iterable<Suite> suites) | 62 ConsoleReporter(Iterable<Suite> suites) |
54 : _multipleSuites = suites.length > 1, | 63 : _multipleSuites = suites.length > 1, |
55 _engine = new Engine(suites) { | 64 _engine = new Engine(suites) { |
56 | 65 |
57 _engine.onTestStarted.listen((liveTest) { | 66 _engine.onTestStarted.listen((liveTest) { |
58 _progressLine(_description(liveTest)); | 67 _progressLine(_description(liveTest)); |
59 liveTest.onStateChange.listen((state) { | 68 liveTest.onStateChange.listen((state) { |
60 if (state.status != Status.complete) return; | 69 if (state.status != Status.complete) return; |
61 if (state.result == Result.success) { | 70 if (state.result == Result.success) { |
62 _passed.add(liveTest); | 71 _passed.add(liveTest); |
63 } else { | 72 } else { |
64 _passed.remove(liveTest); | 73 _passed.remove(liveTest); |
65 _failed.add(liveTest); | 74 _failed.add(liveTest); |
66 } | 75 } |
67 _progressLine(_description(liveTest)); | 76 _progressLine(_description(liveTest)); |
68 }); | 77 }); |
69 | 78 |
70 liveTest.onError.listen((error) { | 79 liveTest.onError.listen((error) { |
71 if (liveTest.state.status != Status.complete) return; | 80 if (liveTest.state.status != Status.complete) return; |
72 | 81 |
73 // TODO(nweiz): don't re-print the progress line if a test has multiple | |
74 // errors in a row. | |
75 _progressLine(_description(liveTest)); | 82 _progressLine(_description(liveTest)); |
76 print(''); | 83 print(''); |
77 print(indent("${error.error}\n${error.stackTrace}")); | 84 print(indent(error.error.toString())); |
| 85 print(indent(terseChain(error.stackTrace).toString())); |
78 }); | 86 }); |
79 }); | 87 }); |
80 } | 88 } |
81 | 89 |
82 /// Runs all tests in all provided suites. | 90 /// Runs all tests in all provided suites. |
83 /// | 91 /// |
84 /// This returns `true` if all tests succeed, and `false` otherwise. It will | 92 /// This returns `true` if all tests succeed, and `false` otherwise. It will |
85 /// only return once all tests have finished running. | 93 /// only return once all tests have finished running. |
86 Future<bool> run() { | 94 Future<bool> run() { |
87 if (_stopwatch.isRunning) { | 95 if (_stopwatch.isRunning) { |
88 throw new StateError("ConsoleReporter.run() may not be called more than " | 96 throw new StateError("ConsoleReporter.run() may not be called more than " |
89 "once."); | 97 "once."); |
90 } | 98 } |
91 | 99 |
| 100 if (_engine.liveTests.isEmpty) { |
| 101 print("No tests ran."); |
| 102 return new Future.value(true); |
| 103 } |
| 104 |
92 _stopwatch.start(); | 105 _stopwatch.start(); |
93 return _engine.run().then((success) { | 106 return _engine.run().then((success) { |
94 if (_engine.liveTests.isEmpty) { | 107 if (success) { |
95 print("\nNo tests ran."); | |
96 } else if (success) { | |
97 _progressLine("All tests passed!"); | 108 _progressLine("All tests passed!"); |
98 print(''); | 109 print(''); |
99 } else { | 110 } else { |
100 _progressLine('Some tests failed.', color: _red); | 111 _progressLine('Some tests failed.', color: _red); |
101 print(''); | 112 print(''); |
102 } | 113 } |
103 | 114 |
104 return success; | 115 return success; |
105 }); | 116 }); |
106 } | 117 } |
107 | 118 |
| 119 /// Signals that the caller is done with any test output and the reporter |
| 120 /// should release any resources it has allocated. |
| 121 Future close() => _engine.close(); |
| 122 |
108 /// Prints a line representing the current state of the tests. | 123 /// Prints a line representing the current state of the tests. |
109 /// | 124 /// |
110 /// [message] goes after the progress report, and may be truncated to fit the | 125 /// [message] goes after the progress report, and may be truncated to fit the |
111 /// entire line within [_lineLength]. If [color] is passed, it's used as the | 126 /// entire line within [_lineLength]. If [color] is passed, it's used as the |
112 /// color for [message]. | 127 /// color for [message]. |
113 void _progressLine(String message, {String color}) { | 128 void _progressLine(String message, {String color}) { |
| 129 // Print nothing if nothing has changed since the last progress line. |
| 130 if (_passed.length == _lastProgressPassed && |
| 131 _failed.length == _lastProgressFailed && |
| 132 message == _lastProgressMessage) { |
| 133 return; |
| 134 } |
| 135 |
| 136 _lastProgressPassed = _passed.length; |
| 137 _lastProgressFailed = _failed.length; |
| 138 _lastProgressMessage = message; |
| 139 |
114 if (color == null) color = ''; | 140 if (color == null) color = ''; |
115 var duration = _stopwatch.elapsed; | 141 var duration = _stopwatch.elapsed; |
116 var buffer = new StringBuffer(); | 142 var buffer = new StringBuffer(); |
117 | 143 |
118 // \r moves back to the beginning of the current line. | 144 // \r moves back to the beginning of the current line. |
119 buffer.write('\r${_timeString(duration)} '); | 145 buffer.write('\r${_timeString(duration)} '); |
120 buffer.write(_green); | 146 buffer.write(_green); |
121 buffer.write('+'); | 147 buffer.write('+'); |
122 buffer.write(_passed.length); | 148 buffer.write(_passed.length); |
123 buffer.write(_noColor); | 149 buffer.write(_noColor); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 | 222 |
197 /// Returns a description of [liveTest]. | 223 /// Returns a description of [liveTest]. |
198 /// | 224 /// |
199 /// This differs from the test's own description in that it may also include | 225 /// This differs from the test's own description in that it may also include |
200 /// the suite's name. | 226 /// the suite's name. |
201 String _description(LiveTest liveTest) { | 227 String _description(LiveTest liveTest) { |
202 if (_multipleSuites) return "${liveTest.suite.name}: ${liveTest.test.name}"; | 228 if (_multipleSuites) return "${liveTest.suite.name}: ${liveTest.test.name}"; |
203 return liveTest.test.name; | 229 return liveTest.test.name; |
204 } | 230 } |
205 } | 231 } |
OLD | NEW |