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