Chromium Code Reviews| 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 /** | 5 /** |
| 6 * A library for writing dart unit tests. | 6 * A library for writing dart unit tests. |
| 7 * | 7 * |
| 8 * ##Concepts## | 8 * ##Concepts## |
| 9 * | 9 * |
| 10 * * Tests: Tests are specified via the top-level function [test], they can be | 10 * * Tests: Tests are specified via the top-level function [test], they can be |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 57 * }); | 57 * }); |
| 58 * }); | 58 * }); |
| 59 * group('group B', () { | 59 * group('group B', () { |
| 60 * test('this B.1', () { | 60 * test('this B.1', () { |
| 61 * int x = 2 + 3; | 61 * int x = 2 + 3; |
| 62 * expect(x).equals(5); | 62 * expect(x).equals(5); |
| 63 * }); | 63 * }); |
| 64 * }); | 64 * }); |
| 65 * } | 65 * } |
| 66 * | 66 * |
| 67 * Asynchronous tests: under the current API (soon to be deprecated): | 67 * Asynchronous tests: if callbacks expect between 0 and 2 positional arguments. |
| 68 * | 68 * |
| 69 * #import('path-to-dart/lib/unittest/unitest.dart'); | 69 * #import('path-to-dart/lib/unittest/unitest.dart'); |
| 70 * #import('dart:dom'); | 70 * #import('dart:dom'); |
| 71 * main() { | 71 * main() { |
| 72 * // use [asyncTest], indicate the expected number of callbacks: | 72 * test('calllback is executed once', () { |
| 73 * asyncTest('this is a test', 1, () { | 73 * // wrap the callback of an asynchronous call with [expectAsync0] if |
| 74 * window.setTimeout(() { | 74 * // the callback takes 0 arguments... |
| 75 * window.setTimeout(expectAsync0(() { | |
| 75 * int x = 2 + 3; | 76 * int x = 2 + 3; |
| 76 * expect(x).equals(5); | 77 * expect(x).equals(5); |
| 77 * // invoke [callbackDone] at the end of the callback. | 78 * }), 0); |
| 78 * callbackDone(); | 79 * }); |
| 79 * }, 0); | 80 * |
| 81 * test('calllback is executed twice', () { | |
| 82 * var callback = expectAsync0(() { | |
| 83 * int x = 2 + 3; | |
| 84 * expect(x).equals(5); | |
| 85 * }, count: 2); // <-- we can indicate multiplicity to [expectAsync0] | |
| 86 * window.setTimeout(callback, 0); | |
| 87 * window.setTimeout(callback, 0); | |
| 80 * }); | 88 * }); |
| 81 * } | 89 * } |
| 82 * | 90 * |
| 83 * We plan to replace this with a different API, one API we are considering is: | 91 * Note: due to some language limitations we have to use different functions |
| 92 * depending on the number of positional arguments of the callback. In the | |
| 93 * future, we plan to expose a single `expectAsync` function that can be used | |
| 94 * regardless of the number of positional arguments. This requires new langauge | |
| 95 * features or fixes to the current spec (e.g. see dartbug.com/2706). | |
|
Bob Nystrom
2012/04/25 18:21:17
This comment is excellent.
| |
| 96 * | |
| 97 * Meanwhile, we plan to add this alternative API for callbacks of more than 2 | |
| 98 * arguments or that take named parameters. (this is not implemented yet, | |
| 99 * but will be coming here soon). | |
| 84 * | 100 * |
| 85 * #import('path-to-dart/lib/unittest/unitest.dart'); | 101 * #import('path-to-dart/lib/unittest/unitest.dart'); |
| 86 * #import('dart:dom'); | 102 * #import('dart:dom'); |
| 87 * main() { | 103 * main() { |
| 88 * test('this is a test', () { | 104 * test('calllback is executed', () { |
| 89 * // wrap the callback of an asynchronous call with [later] | 105 * // indicate ahead of time that an async callback is expected. |
| 90 * window.setTimeout(later(() { | 106 * var async = startAsync(); |
| 91 * int x = 2 + 3; | 107 * window.setTimeout(() { |
| 92 * expect(x).equals(5); | 108 * // Guard the body of the callback, so errors are propagated |
| 109 * // correctly | |
| 110 * guardAsync(() { | |
| 111 * int x = 2 + 3; | |
| 112 * expect(x).equals(5); | |
| 113 * }); | |
| 114 * // indicate that the asynchronous callback was invoked. | |
| 115 * async.complete(); | |
| 93 * }), 0); | 116 * }), 0); |
| 94 * }); | 117 * }); |
| 95 * } | 118 * |
| 96 */ | 119 */ |
| 97 #library('unittest'); | 120 #library('unittest'); |
| 98 | 121 |
| 99 #import('dart:isolate'); | 122 #import('dart:isolate'); |
| 100 | 123 |
| 101 #source('config.dart'); | 124 #source('config.dart'); |
| 102 #source('expectation.dart'); | 125 #source('expectation.dart'); |
| 103 #source('test_case.dart'); | 126 #source('test_case.dart'); |
| 104 | 127 |
| 105 /** [Configuration] used by the unittest library. */ | 128 /** [Configuration] used by the unittest library. */ |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 136 final _RUNNING_TEST = 2; | 159 final _RUNNING_TEST = 2; |
| 137 | 160 |
| 138 /** | 161 /** |
| 139 * Whether an undetected error occurred while running the last test. These | 162 * Whether an undetected error occurred while running the last test. These |
| 140 * errors are commonly caused by DOM callbacks that were not guarded in a | 163 * errors are commonly caused by DOM callbacks that were not guarded in a |
| 141 * try-catch block. | 164 * try-catch block. |
| 142 */ | 165 */ |
| 143 final _UNCAUGHT_ERROR = 3; | 166 final _UNCAUGHT_ERROR = 3; |
| 144 | 167 |
| 145 int _state = _UNINITIALIZED; | 168 int _state = _UNINITIALIZED; |
| 169 String _uncaughtErrorMessage = null; | |
| 146 | 170 |
| 147 final _PASS = 'pass'; | 171 final _PASS = 'pass'; |
| 148 final _FAIL = 'fail'; | 172 final _FAIL = 'fail'; |
| 149 final _ERROR = 'error'; | 173 final _ERROR = 'error'; |
| 150 | 174 |
| 151 /** Creates an expectation for the given value. */ | 175 /** Creates an expectation for the given value. */ |
| 152 Expectation expect(value) => new Expectation(value); | 176 Expectation expect(value) => new Expectation(value); |
| 153 | 177 |
| 154 /** Evaluates the given function and validates that it throws an exception. */ | 178 /** Evaluates the given function and validates that it throws an exception. */ |
| 155 void expectThrow(function) { | 179 void expectThrow(function) { |
| 156 bool threw = false; | 180 bool threw = false; |
| 157 try { | 181 try { |
| 158 function(); | 182 function(); |
| 159 } catch (var e) { | 183 } catch (var e) { |
| 160 threw = true; | 184 threw = true; |
| 161 } | 185 } |
| 162 Expect.equals(true, threw, 'Expected exception but none was thrown.'); | 186 Expect.equals(true, threw, 'Expected exception but none was thrown.'); |
| 163 } | 187 } |
| 164 | 188 |
| 165 /** | 189 /** |
| 166 * Creates a new test case with the given description and body. The | 190 * Creates a new test case with the given description and body. The |
| 167 * description will include the descriptions of any surrounding group() | 191 * description will include the descriptions of any surrounding group() |
| 168 * calls. | 192 * calls. |
| 169 */ | 193 */ |
| 170 void test(String spec, TestFunction body) { | 194 void test(String spec, TestFunction body) { |
| 171 _ensureInitialized(); | 195 ensureInitialized(); |
| 172 | 196 |
| 173 _tests.add(new TestCase(_tests.length + 1, _fullSpec(spec), body, 0)); | 197 _tests.add(new TestCase(_tests.length + 1, _fullSpec(spec), body, 0)); |
| 174 } | 198 } |
| 175 | 199 |
| 176 /** | 200 /** |
| 177 * Creates a new async test case with the given description and body. The | 201 * Creates a new async test case with the given description and body. The |
| 178 * description will include the descriptions of any surrounding group() | 202 * description will include the descriptions of any surrounding group() |
| 179 * calls. | 203 * calls. |
| 180 */ | 204 */ |
| 181 // TODO(sigmund): deprecate this API | 205 // TODO(sigmund): deprecate this API |
| 182 void asyncTest(String spec, int callbacks, TestFunction body) { | 206 void asyncTest(String spec, int callbacks, TestFunction body) { |
| 183 _ensureInitialized(); | 207 ensureInitialized(); |
| 184 | 208 |
| 185 final testCase = new TestCase( | 209 final testCase = new TestCase( |
| 186 _tests.length + 1, _fullSpec(spec), body, callbacks); | 210 _tests.length + 1, _fullSpec(spec), body, callbacks); |
| 187 _tests.add(testCase); | 211 _tests.add(testCase); |
| 188 | 212 |
| 189 if (callbacks < 1) { | 213 if (callbacks < 1) { |
| 190 testCase.error( | 214 testCase.error( |
| 191 'Async tests must wait for at least one callback ', ''); | 215 'Async tests must wait for at least one callback ', ''); |
| 192 } | 216 } |
| 193 } | 217 } |
| 194 | 218 |
| 219 /** Sentinel value for [_SpreadArgsHelper]. */ | |
| 220 class _Sentinel { | |
| 221 const _Sentinel(); | |
| 222 } | |
| 223 | |
| 224 // TODO(sigmund): make a singleton const field when frog supports passing those | |
| 225 // as default values to named arguments. | |
| 226 final _sentinel = const _Sentinel(); | |
| 227 | |
| 228 /** Simulates spread arguments using named arguments. */ | |
| 229 // TODO(sigmund): remove this class and simply use a closure with named | |
| 230 // arguments inside [_expectAsync], once bug 282 is fixed or frog is replaced by | |
| 231 // dart2js. | |
| 232 class _SpreadArgsHelper { | |
| 233 Function callback; | |
| 234 int expectedCalls; | |
| 235 int calls = 0; | |
| 236 TestCase testCase; | |
| 237 _SpreadArgsHelper(this.callback, this.expectedCalls) { | |
| 238 Expect.isTrue(_currentTest < _tests.length); | |
| 239 testCase = _tests[_currentTest]; | |
| 240 testCase.callbacks++; | |
| 241 } | |
| 242 | |
| 243 invoke([arg0 = _sentinel, arg1 = _sentinel, arg2 = _sentinel, | |
| 244 arg3 = _sentinel, arg4 = _sentinel]) { | |
| 245 return _guard(() { | |
| 246 if (!_incrementCall()) { | |
| 247 return; | |
| 248 } else if (arg0 == _sentinel) { | |
| 249 return callback(); | |
| 250 } else if (arg1 == _sentinel) { | |
| 251 return callback(arg0); | |
| 252 } else if (arg2 == _sentinel) { | |
| 253 return callback(arg0, arg1); | |
| 254 } else if (arg3 == _sentinel) { | |
| 255 return callback(arg0, arg1, arg2); | |
| 256 } else if (arg4 == _sentinel) { | |
| 257 return callback(arg0, arg1, arg2, arg3); | |
| 258 } else { | |
| 259 testCase.error( | |
| 260 'unittest lib does not support callbacks with more than 4 arguments', | |
| 261 ''); | |
| 262 _state = _UNCAUGHT_ERROR; | |
| 263 } | |
| 264 }, () { if (calls == expectedCalls) callbackDone(); }); | |
| 265 } | |
| 266 | |
| 267 invoke0() { | |
| 268 return _guard( | |
| 269 () => _incrementCall() ? callback() : null, | |
| 270 () { if (calls == expectedCalls) callbackDone(); }); | |
| 271 } | |
| 272 | |
| 273 invoke1(arg1) { | |
| 274 return _guard( | |
| 275 () => _incrementCall() ? callback(arg1) : null, | |
| 276 () { if (calls == expectedCalls) callbackDone(); }); | |
| 277 } | |
| 278 | |
| 279 invoke2(arg1, arg2) { | |
| 280 return _guard( | |
| 281 () => _incrementCall() ? callback(arg1, arg2) : null, | |
| 282 () { if (calls == expectedCalls) callbackDone(); }); | |
| 283 } | |
| 284 | |
| 285 /** Returns false if we exceded the number of expected calls. */ | |
| 286 bool _incrementCall() { | |
| 287 calls++; | |
| 288 if (calls > expectedCalls) { | |
| 289 testCase.error( | |
| 290 'Callback called more times than expected ($expectedCalls)', | |
| 291 ''); | |
| 292 _state = _UNCAUGHT_ERROR; | |
| 293 return false; | |
| 294 } | |
| 295 return true; | |
| 296 } | |
| 297 } | |
| 298 | |
| 195 /** | 299 /** |
| 196 * Indicate to the unittest framework that a 0-argument callback is expected. | 300 * Indicate that [callback] is expected to be called a [count] number of times |
| 197 * | 301 * (by default 1). The unittest framework will wait for the callback to run the |
| 198 * The framework will wait for the callback to run before it continues with the | 302 * specified [count] times before it continues with the following test. Using |
| 199 * following test. The callback must excute once and only once. Using [later] | 303 * [_expectAsync] will also ensure that errors that occur within [callback] are |
| 200 * will also ensure that errors that occur within the callback are tracked and | 304 * tracked and reported. [callback] should take between 0 and 4 positional |
| 201 * reported by the unittest framework. | 305 * arguments (named arguments are not supported here). |
| 202 */ | 306 */ |
| 203 // TODO(sigmund): expose this functionality | 307 Function _expectAsync(Function callback, [int count = 1]) { |
| 204 Function _later0(Function callback) { | 308 return new _SpreadArgsHelper(callback, count).invoke; |
| 205 Expect.isTrue(_currentTest < _tests.length); | |
| 206 var testCase = _tests[_currentTest]; | |
| 207 testCase.callbacks++; | |
| 208 return () { | |
| 209 _guard(() => callback(), callbackDone); | |
| 210 }; | |
| 211 } | |
| 212 | |
| 213 // TODO(sigmund): expose this functionality | |
| 214 /** Like [_later0] but expecting a callback with 1 argument. */ | |
| 215 Function _later1(Function callback) { | |
| 216 Expect.isTrue(_currentTest < _tests.length); | |
| 217 var testCase = _tests[_currentTest]; | |
| 218 testCase.callbacks++; | |
| 219 return (arg0) { | |
| 220 _guard(() => callback(arg0), callbackDone); | |
| 221 }; | |
| 222 } | |
| 223 | |
| 224 // TODO(sigmund): expose this functionality | |
| 225 /** Like [_later0] but expecting a callback with 2 arguments. */ | |
| 226 Function _later2(Function callback) { | |
| 227 Expect.isTrue(_currentTest < _tests.length); | |
| 228 var testCase = _tests[_currentTest]; | |
| 229 testCase.callbacks++; | |
| 230 return (arg0, arg1) { | |
| 231 _guard(() => callback(arg0, arg1), callbackDone); | |
| 232 }; | |
| 233 } | 309 } |
| 234 | 310 |
| 235 /** | 311 /** |
| 312 * Indicate that [callback] is expected to be called a [count] number of times | |
| 313 * (by default 1). The unittest framework will wait for the callback to run the | |
| 314 * specified [count] times before it continues with the following test. Using | |
| 315 * [expectAsync0] will also ensure that errors that occur within [callback] are | |
| 316 * tracked and reported. [callback] should take 0 positional arguments (named | |
| 317 * arguments are not supported). | |
| 318 */ | |
| 319 // TODO(sigmund): deprecate this API when issue 2706 is fixed. | |
| 320 Function expectAsync0(Function callback, [int count = 1]) { | |
| 321 return new _SpreadArgsHelper(callback, count).invoke0; | |
| 322 } | |
| 323 | |
| 324 /** Like [expectAsync0] but [callback] should take 1 positional argument. */ | |
| 325 // TODO(sigmund): deprecate this API when issue 2706 is fixed. | |
| 326 Function expectAsync1(Function callback, [int count = 1]) { | |
| 327 return new _SpreadArgsHelper(callback, count).invoke1; | |
| 328 } | |
| 329 | |
| 330 /** Like [expectAsync0] but [callback] should take 1 positional argument. */ | |
| 331 // TODO(sigmund): deprecate this API when issue 2706 is fixed. | |
| 332 Function expectAsync2(Function callback, [int count = 1]) { | |
| 333 return new _SpreadArgsHelper(callback, count).invoke2; | |
| 334 } | |
| 335 | |
| 336 /** | |
| 236 * Creates a new named group of tests. Calls to group() or test() within the | 337 * Creates a new named group of tests. Calls to group() or test() within the |
| 237 * body of the function passed to this will inherit this group's description. | 338 * body of the function passed to this will inherit this group's description. |
| 238 */ | 339 */ |
| 239 void group(String description, void body()) { | 340 void group(String description, void body()) { |
| 240 _ensureInitialized(); | 341 ensureInitialized(); |
| 241 | 342 |
| 242 // Concatenate the new group. | 343 // Concatenate the new group. |
| 243 final oldGroup = _currentGroup; | 344 final oldGroup = _currentGroup; |
| 244 if (_currentGroup != '') { | 345 if (_currentGroup != '') { |
| 245 // Add a space. | 346 // Add a space. |
| 246 _currentGroup = '$_currentGroup $description'; | 347 _currentGroup = '$_currentGroup $description'; |
| 247 } else { | 348 } else { |
| 248 // The first group. | 349 // The first group. |
| 249 _currentGroup = description; | 350 _currentGroup = description; |
| 250 } | 351 } |
| 251 | 352 |
| 252 try { | 353 try { |
| 253 body(); | 354 body(); |
| 254 } finally { | 355 } finally { |
| 255 // Now that the group is over, restore the previous one. | 356 // Now that the group is over, restore the previous one. |
| 256 _currentGroup = oldGroup; | 357 _currentGroup = oldGroup; |
| 257 } | 358 } |
| 258 } | 359 } |
| 259 | 360 |
| 260 /** Called by subclasses to indicate that an asynchronous test completed. */ | 361 /** Called by subclasses to indicate that an asynchronous test completed. */ |
| 261 void callbackDone() { | 362 void callbackDone() { |
| 262 _callbacksCalled++; | 363 _callbacksCalled++; |
| 263 final testCase = _tests[_currentTest]; | 364 if (_currentTest < _tests.length) { |
| 264 if (_callbacksCalled > testCase.callbacks) { | 365 final testCase = _tests[_currentTest]; |
| 265 final expected = testCase.callbacks; | 366 if (_callbacksCalled > testCase.callbacks) { |
| 266 testCase.error( | 367 final expected = testCase.callbacks; |
| 267 'More calls to callbackDone() than expected. ' | 368 testCase.error( |
| 268 'Actual: ${_callbacksCalled}, expected: ${expected}', ''); | 369 'More calls to callbackDone() than expected. ' |
| 269 _state = _UNCAUGHT_ERROR; | 370 'Actual: ${_callbacksCalled}, expected: ${expected}', ''); |
| 270 } else if ((_callbacksCalled == testCase.callbacks) && | 371 _state = _UNCAUGHT_ERROR; |
| 271 (_state != _RUNNING_TEST)) { | 372 } else if ((_callbacksCalled == testCase.callbacks) && |
| 272 if (testCase.result == null) testCase.pass(); | 373 (_state != _RUNNING_TEST)) { |
| 273 _currentTest++; | 374 if (testCase.result == null) testCase.pass(); |
| 274 _testRunner(); | 375 _currentTest++; |
| 376 _testRunner(); | |
| 377 } | |
| 378 } else { | |
|
Bob Nystrom
2012/04/25 18:21:17
Remove the empty else clause.
Siggi Cherem (dart-lang)
2012/04/25 18:35:37
Oops, thanks
| |
| 275 } | 379 } |
| 276 } | 380 } |
| 277 | 381 |
| 382 /** Menchanism to notify that an error was caught outside of this library. */ | |
| 278 void notifyError(String msg, String trace) { | 383 void notifyError(String msg, String trace) { |
|
Bob Nystrom
2012/04/25 18:21:17
Rename? See my previous comment.
Siggi Cherem (dart-lang)
2012/04/25 18:35:37
sorry I forgot this one. Done.
| |
| 279 if (_currentTest < _tests.length) { | 384 if (_currentTest < _tests.length) { |
| 280 final testCase = _tests[_currentTest]; | 385 final testCase = _tests[_currentTest]; |
| 281 testCase.error(msg, trace); | 386 testCase.error(msg, trace); |
| 282 _state = _UNCAUGHT_ERROR; | 387 _state = _UNCAUGHT_ERROR; |
| 283 if (testCase.callbacks > 0) { | 388 if (testCase.callbacks > 0) { |
| 284 _currentTest++; | 389 _currentTest++; |
| 285 _testRunner(); | 390 _testRunner(); |
| 286 } | 391 } |
| 392 } else { | |
| 393 _uncaughtErrorMessage = "$msg: $trace"; | |
| 287 } | 394 } |
| 288 } | 395 } |
| 289 | 396 |
| 290 /** Runs [callback] at the end of the event loop. */ | 397 /** Runs [callback] at the end of the event loop. */ |
| 291 _defer(void callback()) { | 398 _defer(void callback()) { |
| 292 // Exploit isolate ports as a platform-independent mechanism to queue a | 399 // Exploit isolate ports as a platform-independent mechanism to queue a |
| 293 // message at the end of the event loop. | 400 // message at the end of the event loop. |
| 294 // TODO(sigmund): expose this functionality somewhere in our libraries. | 401 // TODO(sigmund): expose this functionality somewhere in our libraries. |
| 295 final port = new ReceivePort(); | 402 final port = new ReceivePort(); |
| 296 port.receive((msg, reply) { | 403 port.receive((msg, reply) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 308 assert (_currentTest == 0); | 415 assert (_currentTest == 0); |
| 309 _testRunner(); | 416 _testRunner(); |
| 310 }); | 417 }); |
| 311 } | 418 } |
| 312 | 419 |
| 313 /** | 420 /** |
| 314 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, update | 421 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, update |
| 315 * the [_currentTest] status accordingly. | 422 * the [_currentTest] status accordingly. |
| 316 */ | 423 */ |
| 317 _guard(tryBody, [finallyBody]) { | 424 _guard(tryBody, [finallyBody]) { |
| 318 final testCase = _tests[_currentTest]; | |
| 319 try { | 425 try { |
| 320 tryBody(); | 426 return tryBody(); |
| 321 } catch (ExpectException e, var trace) { | 427 } catch (ExpectException e, var trace) { |
| 322 if (_state != _UNCAUGHT_ERROR) { | 428 if (_state != _UNCAUGHT_ERROR) { |
| 323 //TODO(pquitslund) remove guard once dartc reliably propagates traces | 429 _tests[_currentTest].fail(e.message, trace.toString()); |
| 324 testCase.fail(e.message, trace == null ? '' : trace.toString()); | |
| 325 } | 430 } |
| 326 } catch (var e, var trace) { | 431 } catch (var e, var trace) { |
| 327 if (_state != _UNCAUGHT_ERROR) { | 432 if (_state != _UNCAUGHT_ERROR) { |
| 328 //TODO(pquitslund) remove guard once dartc reliably propagates traces | 433 _tests[_currentTest].error('Caught $e', trace.toString()); |
| 329 testCase.error('Caught ${e}', trace == null ? '' : trace.toString()); | |
| 330 } | 434 } |
| 331 } finally { | 435 } finally { |
| 332 _state = _READY; | 436 _state = _READY; |
| 333 if (finallyBody != null) finallyBody(); | 437 if (finallyBody != null) finallyBody(); |
| 334 } | 438 } |
| 335 } | 439 } |
| 336 | 440 |
| 337 /** | 441 /** |
| 338 * Runs a batch of tests, yielding whenever an asynchronous test starts | 442 * Runs a batch of tests, yielding whenever an asynchronous test starts |
| 339 * running. Tests will resume executing when such asynchronous test calls | 443 * running. Tests will resume executing when such asynchronous test calls |
| 340 * [done] or if it fails with an exception. | 444 * [done] or if it fails with an exception. |
| 341 */ | 445 */ |
| 342 _nextBatch() { | 446 _nextBatch() { |
| 343 while (_currentTest < _tests.length) { | 447 while (_currentTest < _tests.length) { |
| 344 final testCase = _tests[_currentTest]; | 448 final testCase = _tests[_currentTest]; |
| 345 | |
| 346 _guard(() { | 449 _guard(() { |
| 347 _callbacksCalled = 0; | 450 _callbacksCalled = 0; |
| 348 _state = _RUNNING_TEST; | 451 _state = _RUNNING_TEST; |
| 349 | 452 |
| 350 testCase.test(); | 453 testCase.test(); |
| 351 | 454 |
| 352 if (_state != _UNCAUGHT_ERROR) { | 455 if (_state != _UNCAUGHT_ERROR) { |
| 353 if (testCase.callbacks == _callbacksCalled) { | 456 if (testCase.callbacks == _callbacksCalled) { |
| 354 testCase.pass(); | 457 testCase.pass(); |
| 355 } | 458 } |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 373 int testsErrors_ = 0; | 476 int testsErrors_ = 0; |
| 374 | 477 |
| 375 for (TestCase t in _tests) { | 478 for (TestCase t in _tests) { |
| 376 switch (t.result) { | 479 switch (t.result) { |
| 377 case _PASS: testsPassed_++; break; | 480 case _PASS: testsPassed_++; break; |
| 378 case _FAIL: testsFailed_++; break; | 481 case _FAIL: testsFailed_++; break; |
| 379 case _ERROR: testsErrors_++; break; | 482 case _ERROR: testsErrors_++; break; |
| 380 } | 483 } |
| 381 } | 484 } |
| 382 | 485 |
| 383 _config.onDone(testsPassed_, testsFailed_, testsErrors_, _tests); | 486 _config.onDone(testsPassed_, testsFailed_, testsErrors_, _tests, |
| 487 _uncaughtErrorMessage); | |
| 384 } | 488 } |
| 385 | 489 |
| 386 String _fullSpec(String spec) { | 490 String _fullSpec(String spec) { |
| 387 if (spec === null) return '$_currentGroup'; | 491 if (spec === null) return '$_currentGroup'; |
| 388 return _currentGroup != '' ? '$_currentGroup $spec' : spec; | 492 return _currentGroup != '' ? '$_currentGroup $spec' : spec; |
| 389 } | 493 } |
| 390 | 494 |
| 391 /** | 495 /** |
| 392 * Lazily initializes the test library if not already initialized. | 496 * Lazily initializes the test library if not already initialized. |
| 393 */ | 497 */ |
| 394 _ensureInitialized() { | 498 ensureInitialized() { |
| 395 if (_state != _UNINITIALIZED) return; | 499 if (_state != _UNINITIALIZED) return; |
| 396 | 500 |
| 397 _tests = <TestCase>[]; | 501 _tests = <TestCase>[]; |
| 398 _currentGroup = ''; | 502 _currentGroup = ''; |
| 399 _state = _READY; | 503 _state = _READY; |
| 400 _testRunner = _nextBatch; | 504 _testRunner = _nextBatch; |
| 401 | 505 |
| 402 if (_config == null) { | 506 if (_config == null) { |
| 403 _config = new Configuration(); | 507 _config = new Configuration(); |
| 404 } | 508 } |
| 405 _config.onInit(); | 509 _config.onInit(); |
| 406 | 510 |
| 407 // Immediately queue the suite up. It will run after a timeout (i.e. after | 511 // Immediately queue the suite up. It will run after a timeout (i.e. after |
| 408 // main() has returned). | 512 // main() has returned). |
| 409 _defer(_runTests); | 513 _defer(_runTests); |
| 410 } | 514 } |
| 411 | 515 |
| 412 /** Signature for a test function. */ | 516 /** Signature for a test function. */ |
| 413 typedef void TestFunction(); | 517 typedef void TestFunction(); |
| OLD | NEW |