OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 part of unittest; | 5 part of unittest; |
6 | 6 |
| 7 // A custom failure handler for [expect] that routes expect failures |
| 8 // to the config. |
| 9 class _ExpectFailureHandler extends DefaultFailureHandler { |
| 10 Configuration _config; |
| 11 |
| 12 _ExpectFailureHandler(this._config) : super(); |
| 13 |
| 14 void fail(String reason) { |
| 15 _config.onExpectFailure(reason); |
| 16 } |
| 17 } |
| 18 |
7 /** | 19 /** |
8 * Hooks to configure the unittest library for different platforms. This class | 20 * Hooks to configure the unittest library for different platforms. This class |
9 * implements the API in a platform-independent way. Tests that want to take | 21 * implements the API in a platform-independent way. Tests that want to take |
10 * advantage of the platform can create a subclass and override methods from | 22 * advantage of the platform can create a subclass and override methods from |
11 * this class. | 23 * this class. |
12 */ | 24 */ |
13 | 25 |
14 class Configuration { | 26 class Configuration { |
15 // The VM won't shut down if a receive port is open. Use this to make sure | 27 // The VM won't shut down if a receive port is open. Use this to make sure |
16 // we correctly wait for asynchronous tests. | 28 // we correctly wait for asynchronous tests. |
17 ReceivePort _receivePort; | 29 ReceivePort _receivePort; |
18 | 30 |
19 /** | 31 /** |
20 * Subclasses can override this with something useful for diagnostics. | 32 * Subclasses can override this with something useful for diagnostics. |
21 * Particularly useful in cases where we have parent/child configurations | 33 * Particularly useful in cases where we have parent/child configurations |
22 * such as layout tests. | 34 * such as layout tests. |
23 */ | 35 */ |
24 final String name = 'Configuration'; | 36 final String name = 'Configuration'; |
25 | 37 |
26 /** | 38 /** |
27 * If true, then tests are started automatically (otherwise [runTests] | 39 * If true, then tests are started automatically (otherwise [runTests] |
28 * must be called explicitly after the tests are set up. | 40 * must be called explicitly after the tests are set up. |
29 */ | 41 */ |
30 final bool autoStart = true; | 42 final bool autoStart = true; |
31 | 43 |
32 /** | 44 /** |
| 45 * If true (the default), throw an exception at the end if any tests failed. |
| 46 */ |
| 47 bool throwOnTestFailures = true; |
| 48 |
| 49 /** |
| 50 * If true (the default), then tests will stop after the first failed |
| 51 * [expect]. If false, failed [expect]s will not cause the test |
| 52 * to stop (other exceptions will still terminate the test). |
| 53 */ |
| 54 bool stopTestOnExpectFailure = true; |
| 55 |
| 56 // If stopTestOnExpectFailure is false, we need to capture failures, which |
| 57 // we do with this List. |
| 58 List _testLogBuffer = new List(); |
| 59 |
| 60 /** |
| 61 * The constructor sets up a failure handler for [expect] that redirects |
| 62 * [expect] failures to [onExpectFailure]. |
| 63 */ |
| 64 Configuration() { |
| 65 configureExpectFailureHandler(new _ExpectFailureHandler(this)); |
| 66 } |
| 67 /** |
33 * Called as soon as the unittest framework becomes initialized. This is done | 68 * Called as soon as the unittest framework becomes initialized. This is done |
34 * even before tests are added to the test framework. It might be used to | 69 * even before tests are added to the test framework. It might be used to |
35 * determine/debug errors that occur before the test harness starts executing. | 70 * determine/debug errors that occur before the test harness starts executing. |
36 * It is also used to tell the vm or browser that tests are going to be run | 71 * It is also used to tell the vm or browser that tests are going to be run |
37 * asynchronously and that the process should wait until they are done. | 72 * asynchronously and that the process should wait until they are done. |
38 */ | 73 */ |
39 void onInit() { | 74 void onInit() { |
40 _receivePort = new ReceivePort(); | 75 _receivePort = new ReceivePort(); |
41 _postMessage('unittest-suite-wait-for-done'); | 76 _postMessage('unittest-suite-wait-for-done'); |
42 } | 77 } |
43 | 78 |
44 /** Called as soon as the unittest framework starts running. */ | 79 /** Called as soon as the unittest framework starts running. */ |
45 void onStart() {} | 80 void onStart() {} |
46 | 81 |
47 /** | 82 /** |
48 * Called when each test starts. Useful to show intermediate progress on | 83 * Called when each test starts. Useful to show intermediate progress on |
49 * a test suite. | 84 * a test suite. Derived classes should call this first before their own |
| 85 * override code. |
50 */ | 86 */ |
51 void onTestStart(TestCase testCase) { | 87 void onTestStart(TestCase testCase) { |
52 assert(testCase != null); | 88 assert(testCase != null); |
| 89 _testLogBuffer.clear(); |
53 } | 90 } |
54 | 91 |
55 /** | 92 /** |
56 * Called when each test is first completed. Useful to show intermediate | 93 * Called when each test is first completed. Useful to show intermediate |
57 * progress on a test suite. | 94 * progress on a test suite. Derived classes should call this first |
| 95 * before their own override code. |
58 */ | 96 */ |
59 void onTestResult(TestCase testCase) { | 97 void onTestResult(TestCase testCase) { |
60 assert(testCase != null); | 98 assert(testCase != null); |
| 99 if (!stopTestOnExpectFailure && _testLogBuffer.length > 0) { |
| 100 // Write the message/stack pairs up to the last pairs. |
| 101 var reason = new StringBuffer(); |
| 102 for (var i = 0; i < _testLogBuffer.length - 2; i += 2) { |
| 103 reason.write(_testLogBuffer[i]); |
| 104 reason.write('\n'); |
| 105 reason.write(_formatStack(_testLogBuffer[i+1])); |
| 106 reason.write('\n'); |
| 107 } |
| 108 // Write the last message. |
| 109 reason.write(_testLogBuffer[_testLogBuffer.length - 2]); |
| 110 if (testCase.result == PASS) { |
| 111 testCase._result = FAIL; |
| 112 testCase._message = reason.toString(); |
| 113 // Use the last stack as the overall failure stack. |
| 114 testCase._stackTrace = |
| 115 _formatStack(_testLogBuffer[_testLogBuffer.length - 1]); |
| 116 } else { |
| 117 // Add the last stack to the message; we have a further stack |
| 118 // caused by some other failure. |
| 119 reason.write(_formatStack(_testLogBuffer[_testLogBuffer.length - 1])); |
| 120 reason.write('\n'); |
| 121 // Add the existing reason to the end of the expect log to |
| 122 // create the final message. |
| 123 testCase._message = '${reason.toString()}\n${testCase._message}'; |
| 124 } |
| 125 } |
61 } | 126 } |
62 | 127 |
63 /** | 128 /** |
64 * Called when an already completed test changes state; for example a test | 129 * Called when an already completed test changes state; for example a test |
65 * that was marked as passing may later be marked as being in error because | 130 * that was marked as passing may later be marked as being in error because |
66 * it still had callbacks being invoked. | 131 * it still had callbacks being invoked. |
67 */ | 132 */ |
68 void onTestResultChanged(TestCase testCase) { | 133 void onTestResultChanged(TestCase testCase) { |
69 assert(testCase != null); | 134 assert(testCase != null); |
70 } | 135 } |
71 | 136 |
72 /** | 137 /** |
73 * Handles the logging of messages by a test case. The default in | 138 * Handles the logging of messages by a test case. The default in |
74 * this base configuration is to call print(); | 139 * this base configuration is to call print(); |
75 */ | 140 */ |
76 void onLogMessage(TestCase testCase, String message) { | 141 void onLogMessage(TestCase testCase, String message) { |
77 print(message); | 142 print(message); |
78 } | 143 } |
79 | 144 |
80 /** | 145 /** |
| 146 * Handles failures from expect(). The default in |
| 147 * this base configuration is to throw an exception; |
| 148 */ |
| 149 void onExpectFailure(String reason) { |
| 150 if (stopTestOnExpectFailure) { |
| 151 throw new TestFailure(reason); |
| 152 } else { |
| 153 _testLogBuffer.add(reason); |
| 154 try { |
| 155 throw ''; |
| 156 } catch (_, stack) { |
| 157 _testLogBuffer.add(stack); |
| 158 } |
| 159 } |
| 160 } |
| 161 |
| 162 /** |
81 * Called with the result of all test cases. The default implementation prints | 163 * Called with the result of all test cases. The default implementation prints |
82 * the result summary using the built-in [print] command. Browser tests | 164 * the result summary using the built-in [print] command. Browser tests |
83 * commonly override this to reformat the output. | 165 * commonly override this to reformat the output. |
84 * | 166 * |
85 * When [uncaughtError] is not null, it contains an error that occured outside | 167 * When [uncaughtError] is not null, it contains an error that occured outside |
86 * of tests (e.g. setting up the test). | 168 * of tests (e.g. setting up the test). |
87 */ | 169 */ |
88 void onSummary(int passed, int failed, int errors, List<TestCase> results, | 170 void onSummary(int passed, int failed, int errors, List<TestCase> results, |
89 String uncaughtError) { | 171 String uncaughtError) { |
90 // Print each test's result. | 172 // Print each test's result. |
(...skipping 29 matching lines...) Expand all Loading... |
120 /** | 202 /** |
121 * Called when the unittest framework is done running. [success] indicates | 203 * Called when the unittest framework is done running. [success] indicates |
122 * whether all tests passed successfully. | 204 * whether all tests passed successfully. |
123 */ | 205 */ |
124 void onDone(bool success) { | 206 void onDone(bool success) { |
125 if (success) { | 207 if (success) { |
126 _postMessage('unittest-suite-success'); | 208 _postMessage('unittest-suite-success'); |
127 _receivePort.close(); | 209 _receivePort.close(); |
128 } else { | 210 } else { |
129 _receivePort.close(); | 211 _receivePort.close(); |
130 throw new Exception('Some tests failed.'); | 212 if (throwOnTestFailures) { |
| 213 throw new Exception('Some tests failed.'); |
| 214 } |
131 } | 215 } |
132 } | 216 } |
133 | 217 |
134 String _indent(String str) { | 218 String _indent(String str) { |
135 // TODO(nweiz): Use this simpler code once issue 2980 is fixed. | 219 // TODO(nweiz): Use this simpler code once issue 2980 is fixed. |
136 // return str.replaceAll(new RegExp("^", multiLine: true), " "); | 220 // return str.replaceAll(new RegExp("^", multiLine: true), " "); |
137 | 221 |
138 return str.split("\n").map((line) => " $line").join("\n"); | 222 return str.split("\n").map((line) => " $line").join("\n"); |
139 } | 223 } |
140 | 224 |
141 /** Handle errors that happen outside the tests. */ | 225 /** Handle errors that happen outside the tests. */ |
142 // TODO(vsm): figure out how to expose the stack trace here | 226 // TODO(vsm): figure out how to expose the stack trace here |
143 // Currently e.message works in dartium, but not in dartc. | 227 // Currently e.message works in dartium, but not in dartc. |
144 void handleExternalError(e, String message, [String stack = '']) => | 228 void handleExternalError(e, String message, [String stack = '']) => |
145 _reportTestError('$message\nCaught $e', stack); | 229 _reportTestError('$message\nCaught $e', stack); |
146 | 230 |
147 _postMessage(String message) { | 231 _postMessage(String message) { |
148 // In dart2js browser tests, the JavaScript-based test controller | 232 // In dart2js browser tests, the JavaScript-based test controller |
149 // intercepts calls to print and listens for "secret" messages. | 233 // intercepts calls to print and listens for "secret" messages. |
150 print(message); | 234 print(message); |
151 } | 235 } |
152 } | 236 } |
OLD | NEW |