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 * To import this library, specify the relative path to | 8 * To import this library, specify the relative path to |
| 9 * lib/unittest/unittest.dart. | 9 * lib/unittest/unittest.dart. |
| 10 * | 10 * |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 147 #source('map_matchers.dart'); | 147 #source('map_matchers.dart'); |
| 148 #source('matcher.dart'); | 148 #source('matcher.dart'); |
| 149 #source('numeric_matchers.dart'); | 149 #source('numeric_matchers.dart'); |
| 150 #source('operator_matchers.dart'); | 150 #source('operator_matchers.dart'); |
| 151 #source('string_matchers.dart'); | 151 #source('string_matchers.dart'); |
| 152 #source('test_case.dart'); | 152 #source('test_case.dart'); |
| 153 | 153 |
| 154 /** [Configuration] used by the unittest library. */ | 154 /** [Configuration] used by the unittest library. */ |
| 155 Configuration _config = null; | 155 Configuration _config = null; |
| 156 | 156 |
| 157 /** Set the [Configuration] used by the unittest library. */ | 157 /** Set the [Configuration] used by the unittest library.*/ |
|
Bob Nystrom
2012/06/13 23:52:29
?
gram
2012/06/14 00:50:58
Done.
| |
| 158 void configure(Configuration config) { | 158 void configure(Configuration config) { |
| 159 _config = config; | 159 _config = config; |
| 160 } | 160 } |
| 161 | 161 |
| 162 /** | 162 /** |
| 163 * Description text of the current test group. If multiple groups are nested, | 163 * Description text of the current test group. If multiple groups are nested, |
| 164 * this will contain all of their text concatenated. | 164 * this will contain all of their text concatenated. |
| 165 */ | 165 */ |
| 166 String _currentGroup = ''; | 166 String _currentGroup = ''; |
| 167 | 167 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 289 | 289 |
| 290 // TODO(sigmund): make a singleton const field when frog supports passing those | 290 // TODO(sigmund): make a singleton const field when frog supports passing those |
| 291 // as default values to named arguments. | 291 // as default values to named arguments. |
| 292 final _sentinel = const _Sentinel(); | 292 final _sentinel = const _Sentinel(); |
| 293 | 293 |
| 294 /** Simulates spread arguments using named arguments. */ | 294 /** Simulates spread arguments using named arguments. */ |
| 295 // TODO(sigmund): remove this class and simply use a closure with named | 295 // TODO(sigmund): remove this class and simply use a closure with named |
| 296 // arguments inside [_expectAsync], once bug 282 is fixed or frog is replaced by | 296 // arguments inside [_expectAsync], once bug 282 is fixed or frog is replaced by |
| 297 // dart2js. | 297 // dart2js. |
| 298 class _SpreadArgsHelper { | 298 class _SpreadArgsHelper { |
| 299 Function callback; | 299 Function _callback; |
| 300 int expectedCalls; | 300 int _expectedCalls; |
| 301 int calls = 0; | 301 int _calls = 0; |
| 302 TestCase testCase; | 302 TestCase _testCase; |
| 303 _SpreadArgsHelper(this.callback, this.expectedCalls) { | 303 Function _shouldCallBack; |
| 304 Function _isDone; | |
| 305 | |
| 306 _Init(Function callback, Function shouldCallBack, Function isDone, | |
|
Siggi Cherem (dart-lang)
2012/06/13 23:43:53
-> lower case.
Bob Nystrom
2012/06/13 23:52:29
Can you use a delegating constructor for this? Som
gram
2012/06/14 00:50:58
Done.
gram
2012/06/14 00:50:58
I tried this originally. It didn't work because se
| |
| 307 [expectedCalls = 0]) { | |
| 304 Expect.isTrue(_currentTest < _tests.length); | 308 Expect.isTrue(_currentTest < _tests.length); |
|
Bob Nystrom
2012/06/13 23:52:29
This Expect call is weird. Make it an assert inste
gram
2012/06/14 00:50:58
Made assert.
| |
| 305 testCase = _tests[_currentTest]; | 309 _callback = callback; |
| 306 testCase.callbacks++; | 310 _shouldCallBack = shouldCallBack; |
| 311 _isDone = isDone; | |
| 312 _expectedCalls = expectedCalls; | |
| 313 _testCase = _tests[_currentTest]; | |
| 314 _testCase.callbacks++; | |
| 315 } | |
| 316 | |
| 317 _SpreadArgsHelper( callback, shouldCallBack, isDone) { | |
|
Siggi Cherem (dart-lang)
2012/06/13 23:43:53
remove extra space
Bob Nystrom
2012/06/13 23:52:29
No space after '('.
gram
2012/06/14 00:50:58
Done.
gram
2012/06/14 00:50:58
Done.
| |
| 318 _Init(callback, shouldCallBack, isDone); | |
| 319 } | |
| 320 | |
| 321 _SpreadArgsHelper.fixedCallCount(callback, expectedCalls) { | |
|
Siggi Cherem (dart-lang)
2012/06/13 23:43:53
let's make _callback final and change all 3 constr
gram
2012/06/14 00:50:58
Tried this; it doesn't work for the same reason de
| |
| 322 _Init(callback, _checkCallCount, _allCallsDone, expectedCalls); | |
| 323 } | |
| 324 | |
| 325 _SpreadArgsHelper.variableCallCount(callback, isDone) { | |
| 326 _Init(callback, _always, isDone); | |
| 327 } | |
| 328 | |
| 329 _after() { | |
| 330 if (_isDone()) | |
|
Siggi Cherem (dart-lang)
2012/06/13 23:43:53
style: add { } or merge this and the next line in
gram
2012/06/14 00:50:58
Done.
| |
| 331 _handleAllCallbacksDone(); | |
|
Bob Nystrom
2012/06/13 23:52:29
Make this one line or use {}.
gram
2012/06/14 00:50:58
Done.
| |
| 332 } | |
| 333 | |
| 334 _allCallsDone() { | |
|
Bob Nystrom
2012/06/13 23:52:29
Make this an =>?
gram
2012/06/14 00:50:58
Done.
| |
| 335 return (_calls == _expectedCalls); | |
| 336 } | |
| 337 | |
| 338 _always() { | |
| 339 // always run except if the test is done | |
|
Bob Nystrom
2012/06/13 23:52:29
Full sentence: "Always... done."
gram
2012/06/14 00:50:58
Done.
| |
| 340 if (_testCase.isComplete) { | |
| 341 _testCase.error( | |
| 342 'Callback called after already being marked as done ($_calls)', | |
|
Bob Nystrom
2012/06/13 23:52:29
Indent another 2.
gram
2012/06/14 00:50:58
Done.
| |
| 343 ''); | |
| 344 _state = _UNCAUGHT_ERROR; | |
|
Bob Nystrom
2012/06/13 23:52:29
Indent +1.
gram
2012/06/14 00:50:58
Done.
| |
| 345 return false; | |
| 346 } else { | |
| 347 return true; | |
| 348 } | |
| 307 } | 349 } |
| 308 | 350 |
| 309 invoke([arg0 = _sentinel, arg1 = _sentinel, arg2 = _sentinel, | 351 invoke([arg0 = _sentinel, arg1 = _sentinel, arg2 = _sentinel, |
| 310 arg3 = _sentinel, arg4 = _sentinel]) { | 352 arg3 = _sentinel, arg4 = _sentinel]) { |
| 311 return guardAsync(() { | 353 return guardAsync(() { |
| 312 if (!_incrementCall()) { | 354 ++_calls; |
| 355 if (!_shouldCallBack()) { | |
| 313 return; | 356 return; |
| 314 } else if (arg0 == _sentinel) { | 357 } else if (arg0 == _sentinel) { |
| 315 return callback(); | 358 return _callback(); |
| 316 } else if (arg1 == _sentinel) { | 359 } else if (arg1 == _sentinel) { |
| 317 return callback(arg0); | 360 return _callback(arg0); |
| 318 } else if (arg2 == _sentinel) { | 361 } else if (arg2 == _sentinel) { |
| 319 return callback(arg0, arg1); | 362 return _callback(arg0, arg1); |
| 320 } else if (arg3 == _sentinel) { | 363 } else if (arg3 == _sentinel) { |
| 321 return callback(arg0, arg1, arg2); | 364 return _callback(arg0, arg1, arg2); |
| 322 } else if (arg4 == _sentinel) { | 365 } else if (arg4 == _sentinel) { |
| 323 return callback(arg0, arg1, arg2, arg3); | 366 return _callback(arg0, arg1, arg2, arg3); |
| 324 } else { | 367 } else { |
| 325 testCase.error( | 368 _testCase.error( |
| 326 'unittest lib does not support callbacks with more than 4 arguments', | 369 'unittest lib does not support callbacks with more than 4 arguments', |
| 327 ''); | 370 ''); |
| 328 _state = _UNCAUGHT_ERROR; | 371 _state = _UNCAUGHT_ERROR; |
| 329 } | 372 } |
| 330 }, () { if (calls == expectedCalls) callbackDone(); }); | 373 }, |
| 374 _after); | |
| 331 } | 375 } |
| 332 | 376 |
| 333 invoke0() { | 377 invoke0() { |
| 334 return guardAsync( | 378 return guardAsync( |
| 335 () => _incrementCall() ? callback() : null, | 379 () { if (_shouldCallBack()) _callback(); }, |
| 336 () { if (calls == expectedCalls) callbackDone(); }); | 380 _after); |
| 337 } | 381 } |
| 338 | 382 |
| 339 invoke1(arg1) { | 383 invoke1(arg1) { |
| 340 return guardAsync( | 384 return guardAsync( |
| 341 () => _incrementCall() ? callback(arg1) : null, | 385 () { if (_shouldCallBack()) _callback(arg1); }, |
| 342 () { if (calls == expectedCalls) callbackDone(); }); | 386 _after); |
| 343 } | 387 } |
| 344 | 388 |
| 345 invoke2(arg1, arg2) { | 389 invoke2(arg1, arg2) { |
| 346 return guardAsync( | 390 return guardAsync( |
| 347 () => _incrementCall() ? callback(arg1, arg2) : null, | 391 () { if (_shouldCallBack()) _callback(arg1, arg2); }, |
| 348 () { if (calls == expectedCalls) callbackDone(); }); | 392 _after); |
| 349 } | 393 } |
| 350 | 394 |
| 351 /** Returns false if we exceded the number of expected calls. */ | 395 /** Returns false if we exceded the number of expected calls. */ |
| 352 bool _incrementCall() { | 396 bool _checkCallCount() { |
| 353 calls++; | 397 if (_calls > _expectedCalls) { |
| 354 if (calls > expectedCalls) { | 398 _testCase.error( |
| 355 testCase.error( | 399 'Callback called more times than expected ($_calls > $_expectedCalls)', |
|
Bob Nystrom
2012/06/13 23:52:29
Indent another 1.
gram
2012/06/14 00:50:58
Done.
| |
| 356 'Callback called more times than expected ($calls > $expectedCalls)', | |
| 357 ''); | 400 ''); |
| 358 _state = _UNCAUGHT_ERROR; | 401 _state = _UNCAUGHT_ERROR; |
| 359 return false; | 402 return false; |
| 360 } | 403 } |
| 361 return true; | 404 return true; |
| 362 } | 405 } |
| 363 } | 406 } |
| 364 | 407 |
| 365 /** | 408 /** |
| 366 * Indicate that [callback] is expected to be called a [count] number of times | 409 * Indicate that [callback] is expected to be called a [count] number of times |
| 367 * (by default 1). The unittest framework will wait for the callback to run the | 410 * (by default 1). The unittest framework will wait for the callback to run the |
| 368 * specified [count] times before it continues with the following test. Using | 411 * specified [count] times before it continues with the following test. Using |
| 369 * [_expectAsync] will also ensure that errors that occur within [callback] are | 412 * [_expectAsync] will also ensure that errors that occur within [callback] are |
| 370 * tracked and reported. [callback] should take between 0 and 4 positional | 413 * tracked and reported. [callback] should take between 0 and 4 positional |
| 371 * arguments (named arguments are not supported here). | 414 * arguments (named arguments are not supported here). |
| 372 */ | 415 */ |
| 373 Function _expectAsync(Function callback, [int count = 1]) { | 416 Function _expectAsync(Function callback, [int count = 1]) { |
| 374 return new _SpreadArgsHelper(callback, count).invoke; | 417 return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke; |
| 375 } | 418 } |
| 376 | 419 |
| 377 /** | 420 /** |
| 378 * Indicate that [callback] is expected to be called a [count] number of times | 421 * Indicate that [callback] is expected to be called a [count] number of times |
| 379 * (by default 1). The unittest framework will wait for the callback to run the | 422 * (by default 1). The unittest framework will wait for the callback to run the |
| 380 * specified [count] times before it continues with the following test. Using | 423 * specified [count] times before it continues with the following test. Using |
| 381 * [expectAsync0] will also ensure that errors that occur within [callback] are | 424 * [expectAsync0] will also ensure that errors that occur within [callback] are |
| 382 * tracked and reported. [callback] should take 0 positional arguments (named | 425 * tracked and reported. [callback] should take 0 positional arguments (named |
| 383 * arguments are not supported). | 426 * arguments are not supported). |
| 384 */ | 427 */ |
| 385 // TODO(sigmund): deprecate this API when issue 2706 is fixed. | 428 // TODO(sigmund): deprecate this API when issue 2706 is fixed. |
| 386 Function expectAsync0(Function callback, [int count = 1]) { | 429 Function expectAsync0(Function callback, [int count = 1]) { |
| 387 return new _SpreadArgsHelper(callback, count).invoke0; | 430 return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke0; |
| 388 } | 431 } |
| 389 | 432 |
| 390 /** Like [expectAsync0] but [callback] should take 1 positional argument. */ | 433 /** Like [expectAsync0] but [callback] should take 1 positional argument. */ |
| 391 // TODO(sigmund): deprecate this API when issue 2706 is fixed. | 434 // TODO(sigmund): deprecate this API when issue 2706 is fixed. |
| 392 Function expectAsync1(Function callback, [int count = 1]) { | 435 Function expectAsync1(Function callback, [int count = 1]) { |
| 393 return new _SpreadArgsHelper(callback, count).invoke1; | 436 return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke1; |
| 394 } | 437 } |
| 395 | 438 |
| 396 /** Like [expectAsync0] but [callback] should take 2 positional arguments. */ | 439 /** Like [expectAsync0] but [callback] should take 2 positional arguments. */ |
| 397 // TODO(sigmund): deprecate this API when issue 2706 is fixed. | 440 // TODO(sigmund): deprecate this API when issue 2706 is fixed. |
| 398 Function expectAsync2(Function callback, [int count = 1]) { | 441 Function expectAsync2(Function callback, [int count = 1]) { |
| 399 return new _SpreadArgsHelper(callback, count).invoke2; | 442 return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke2; |
| 443 } | |
| 444 | |
| 445 /** | |
| 446 * Indicate that [callback] is expected to be called until [isDone] returns | |
| 447 * true. The unittest framework check [isDone] after each callback and only | |
|
Bob Nystrom
2012/06/13 23:52:29
"check" -> "checks"
gram
2012/06/14 00:50:58
Done.
| |
| 448 * when it returns true will it continue with the following test. Using | |
| 449 * [expectAsyncUntil] will also ensure that errors that occur within | |
| 450 * [callback] are tracked and reported. [callback] should take between 0 and | |
| 451 * 4 positional arguments (named arguments are not supported). | |
| 452 */ | |
| 453 Function expectAsyncUntil(Function callback, Function isDone) { | |
|
Siggi Cherem (dart-lang)
2012/06/13 23:43:53
make this private until issue 2706 gets fixed
gram
2012/06/14 00:50:58
Done.
| |
| 454 return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke; | |
| 455 } | |
| 456 | |
| 457 /** | |
| 458 * Indicate that [callback] is expected to be called until [isDone] returns | |
| 459 * true. The unittest framework check [isDone] after each callback and only | |
| 460 * when it returns true will it continue with the following test. Using | |
| 461 * [expectAsyncUntil0] will also ensure that errors that occur within | |
| 462 * [callback] are tracked and reported. [callback] should take 0 positional | |
| 463 * arguments (named arguments are not supported). | |
| 464 */ | |
| 465 // TODO(sigmund): deprecate this API when issue 2706 is fixed. | |
| 466 Function expectAsyncUntil0(Function callback, Function isDone) { | |
| 467 return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke0; | |
| 468 } | |
| 469 | |
| 470 /** | |
| 471 * Like [expectAsyncUntil0] but [callback] should take 1 positional argument. | |
| 472 */ | |
| 473 // TODO(sigmund): deprecate this API when issue 2706 is fixed. | |
| 474 Function expectAsyncUntil1(Function callback, Function isDone) { | |
| 475 return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke1; | |
| 476 } | |
| 477 | |
| 478 /** | |
| 479 * Like [expectAsyncUntil0] but [callback] should take 2 positional arguments. | |
| 480 */ | |
| 481 // TODO(sigmund): deprecate this API when issue 2706 is fixed. | |
| 482 Function expectAsyncUntil2(Function callback, Function isDone) { | |
| 483 return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke2; | |
| 400 } | 484 } |
| 401 | 485 |
| 402 /** | 486 /** |
| 403 * Creates a new named group of tests. Calls to group() or test() within the | 487 * Creates a new named group of tests. Calls to group() or test() within the |
| 404 * body of the function passed to this will inherit this group's description. | 488 * body of the function passed to this will inherit this group's description. |
| 405 */ | 489 */ |
| 406 void group(String description, void body()) { | 490 void group(String description, void body()) { |
| 407 ensureInitialized(); | 491 ensureInitialized(); |
| 408 | 492 |
| 409 // Concatenate the new group. | 493 // Concatenate the new group. |
| 410 final oldGroup = _currentGroup; | 494 final oldGroup = _currentGroup; |
| 411 if (_currentGroup != '') { | 495 if (_currentGroup != '') { |
| 412 // Add a space. | 496 // Add a space. |
| 413 _currentGroup = '$_currentGroup $description'; | 497 _currentGroup = '$_currentGroup $description'; |
| 414 } else { | 498 } else { |
| 415 // The first group. | 499 // The first group. |
| 416 _currentGroup = description; | 500 _currentGroup = description; |
| 417 } | 501 } |
| 418 | 502 |
| 419 try { | 503 try { |
| 420 body(); | 504 body(); |
| 421 } finally { | 505 } finally { |
| 422 // Now that the group is over, restore the previous one. | 506 // Now that the group is over, restore the previous one. |
| 423 _currentGroup = oldGroup; | 507 _currentGroup = oldGroup; |
| 424 } | 508 } |
| 425 } | 509 } |
| 426 | 510 |
| 427 /** Called by subclasses to indicate that an asynchronous test completed. */ | 511 /** Called by subclasses to indicate that an asynchronous test completed. */ |
| 428 void callbackDone() { | 512 void _handleAllCallbacksDone() { |
| 429 // TODO (gram): we defer this to give the nextBatch recursive | 513 // TODO (gram): we defer this to give the nextBatch recursive |
| 430 // stack a chance to unwind. This is a temporary hack but | 514 // stack a chance to unwind. This is a temporary hack but |
| 431 // really a bunch of code here needs to be fixed. We have a | 515 // really a bunch of code here needs to be fixed. We have a |
| 432 // single array that is being iterated through by nextBatch(), | 516 // single array that is being iterated through by nextBatch(), |
| 433 // which is recursively invoked in the case of async tests that | 517 // which is recursively invoked in the case of async tests that |
| 434 // run synchronously. Bad things can then happen. | 518 // run synchronously. Bad things can then happen. |
| 435 _defer(() { | 519 _defer(() { |
| 436 _callbacksCalled++; | 520 _callbacksCalled++; |
| 437 if (_currentTest < _tests.length) { | 521 if (_currentTest < _tests.length) { |
| 438 final testCase = _tests[_currentTest]; | 522 final testCase = _tests[_currentTest]; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 534 * Runs a batch of tests, yielding whenever an asynchronous test starts | 618 * Runs a batch of tests, yielding whenever an asynchronous test starts |
| 535 * running. Tests will resume executing when such asynchronous test calls | 619 * running. Tests will resume executing when such asynchronous test calls |
| 536 * [done] or if it fails with an exception. | 620 * [done] or if it fails with an exception. |
| 537 */ | 621 */ |
| 538 _nextBatch() { | 622 _nextBatch() { |
| 539 while (_currentTest < _tests.length) { | 623 while (_currentTest < _tests.length) { |
| 540 final testCase = _tests[_currentTest]; | 624 final testCase = _tests[_currentTest]; |
| 541 guardAsync(() { | 625 guardAsync(() { |
| 542 _callbacksCalled = 0; | 626 _callbacksCalled = 0; |
| 543 _state = _RUNNING_TEST; | 627 _state = _RUNNING_TEST; |
| 544 | |
| 545 testCase.test(); | 628 testCase.test(); |
| 546 | 629 |
| 547 if (_state != _UNCAUGHT_ERROR) { | 630 if (_state != _UNCAUGHT_ERROR) { |
| 548 if (testCase.callbacks == _callbacksCalled) { | 631 if (testCase.callbacks == _callbacksCalled) { |
| 549 testCase.pass(); | 632 testCase.pass(); |
| 550 } | 633 } |
| 551 } | 634 } |
| 552 }); | 635 }); |
| 553 | 636 |
| 554 if (!testCase.isComplete && testCase.callbacks > 0) return; | 637 if (!testCase.isComplete && testCase.callbacks > 0) return; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 588 throw new ExpectException(message); | 671 throw new ExpectException(message); |
| 589 } | 672 } |
| 590 | 673 |
| 591 /** | 674 /** |
| 592 * Lazily initializes the test library if not already initialized. | 675 * Lazily initializes the test library if not already initialized. |
| 593 */ | 676 */ |
| 594 ensureInitialized() { | 677 ensureInitialized() { |
| 595 if (_state != _UNINITIALIZED) return; | 678 if (_state != _UNINITIALIZED) return; |
| 596 | 679 |
| 597 _tests = <TestCase>[]; | 680 _tests = <TestCase>[]; |
| 681 _uncaughtErrorMessage = null; | |
| 682 _currentTest = 0; | |
| 598 _currentGroup = ''; | 683 _currentGroup = ''; |
| 599 _state = _READY; | 684 _state = _READY; |
| 600 _testRunner = _nextBatch; | 685 _testRunner = _nextBatch; |
| 601 | 686 |
| 602 if (_config == null) { | 687 if (_config == null) { |
| 603 _config = new Configuration(); | 688 _config = new Configuration(); |
| 604 } | 689 } |
| 605 _config.onInit(); | 690 _config.onInit(); |
| 606 | 691 |
| 607 // Immediately queue the suite up. It will run after a timeout (i.e. after | 692 // Immediately queue the suite up. It will run after a timeout (i.e. after |
| 608 // main() has returned). | 693 // main() has returned). |
| 609 _defer(_runTests); | 694 _defer(_runTests); |
| 610 } | 695 } |
| 611 | 696 |
| 612 /** Signature for a test function. */ | 697 /** Signature for a test function. */ |
| 613 typedef void TestFunction(); | 698 typedef void TestFunction(); |
| OLD | NEW |