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 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 316 // as default values to named arguments. | 316 // as default values to named arguments. |
| 317 final _sentinel = const _Sentinel(); | 317 final _sentinel = const _Sentinel(); |
| 318 | 318 |
| 319 /** Simulates spread arguments using named arguments. */ | 319 /** Simulates spread arguments using named arguments. */ |
| 320 // TODO(sigmund): remove this class and simply use a closure with named | 320 // TODO(sigmund): remove this class and simply use a closure with named |
| 321 // arguments (if still applicable). | 321 // arguments (if still applicable). |
| 322 class _SpreadArgsHelper { | 322 class _SpreadArgsHelper { |
| 323 Function _callback; | 323 Function _callback; |
| 324 int _expectedCalls; | 324 int _expectedCalls; |
| 325 int _calls = 0; | 325 int _calls = 0; |
| 326 int _testNum; | |
| 326 TestCase _testCase; | 327 TestCase _testCase; |
| 327 Function _shouldCallBack; | 328 Function _shouldCallBack; |
| 328 Function _isDone; | 329 Function _isDone; |
| 329 | 330 |
| 330 _init(Function callback, Function shouldCallBack, Function isDone, | 331 _init(Function callback, Function shouldCallBack, Function isDone, |
| 331 [expectedCalls = 0]) { | 332 [expectedCalls = 0]) { |
| 332 ensureInitialized(); | 333 ensureInitialized(); |
| 333 assert(_currentTest < _tests.length); | 334 assert(_currentTest < _tests.length); |
| 334 _callback = callback; | 335 _callback = callback; |
| 335 _shouldCallBack = shouldCallBack; | 336 _shouldCallBack = shouldCallBack; |
| 336 _isDone = isDone; | 337 _isDone = isDone; |
| 337 _expectedCalls = expectedCalls; | 338 _expectedCalls = expectedCalls; |
| 339 _testNum = _currentTest; | |
| 338 _testCase = _tests[_currentTest]; | 340 _testCase = _tests[_currentTest]; |
| 339 if (expectedCalls > 0) { | 341 if (expectedCalls > 0) { |
| 340 _testCase.callbacks++; | 342 _testCase.callbacks++; |
| 341 } | 343 } |
| 342 } | 344 } |
| 343 | 345 |
| 344 _SpreadArgsHelper(callback, shouldCallBack, isDone) { | 346 _SpreadArgsHelper(callback, shouldCallBack, isDone) { |
| 345 _init(callback, shouldCallBack, isDone); | 347 _init(callback, shouldCallBack, isDone); |
| 346 } | 348 } |
| 347 | 349 |
| 348 _SpreadArgsHelper.fixedCallCount(callback, expectedCalls) { | 350 _SpreadArgsHelper.fixedCallCount(callback, expectedCalls) { |
| 349 _init(callback, _checkCallCount, _allCallsDone, expectedCalls); | 351 _init(callback, _checkCallCount, _allCallsDone, expectedCalls); |
| 350 } | 352 } |
| 351 | 353 |
| 352 _SpreadArgsHelper.variableCallCount(callback, isDone) { | 354 _SpreadArgsHelper.variableCallCount(callback, isDone) { |
| 353 _init(callback, _always, isDone, 1); | 355 _init(callback, _always, isDone, 1); |
| 354 } | 356 } |
| 355 | 357 |
| 358 _SpreadArgsHelper.optionalCalls(callback) { | |
| 359 _init(callback, _always, _never, 0); | |
|
Siggi Cherem (dart-lang)
2012/08/02 00:19:07
seems that _never will never be used anywhere else
gram
2012/08/02 00:41:32
Done.
| |
| 360 } | |
| 361 | |
| 356 _after() { | 362 _after() { |
| 357 if (_isDone()) { | 363 if (_isDone()) { |
| 358 _handleAllCallbacksDone(); | 364 _handleAllCallbacksDone(); |
| 359 } | 365 } |
| 360 } | 366 } |
| 361 | 367 |
| 362 _allCallsDone() => _calls == _expectedCalls; | 368 _allCallsDone() => _calls == _expectedCalls; |
| 363 | 369 |
| 370 _never() => false; | |
| 371 | |
| 364 _always() { | 372 _always() { |
| 365 // Always run except if the test is done. | 373 // Always run except if the test is done. |
| 366 if (_testCase.isComplete) { | 374 if (_testCase.isComplete) { |
| 367 _testCase.error( | 375 _testCase.error( |
| 368 'Callback called after already being marked as done ($_calls).', | 376 'Callback called after already being marked as done ($_calls).', |
| 369 ''); | 377 ''); |
| 370 _state = _UNCAUGHT_ERROR; | 378 _state = _UNCAUGHT_ERROR; |
| 371 return false; | 379 return false; |
| 372 } else { | 380 } else { |
| 373 return true; | 381 return true; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 391 } else if (arg4 == _sentinel) { | 399 } else if (arg4 == _sentinel) { |
| 392 return _callback(arg0, arg1, arg2, arg3); | 400 return _callback(arg0, arg1, arg2, arg3); |
| 393 } else { | 401 } else { |
| 394 _testCase.error( | 402 _testCase.error( |
| 395 'unittest lib does not support callbacks with more than' | 403 'unittest lib does not support callbacks with more than' |
| 396 ' 4 arguments.', | 404 ' 4 arguments.', |
| 397 ''); | 405 ''); |
| 398 _state = _UNCAUGHT_ERROR; | 406 _state = _UNCAUGHT_ERROR; |
| 399 } | 407 } |
| 400 }, | 408 }, |
| 401 _after); | 409 _after, _testNum); |
| 402 } | 410 } |
| 403 | 411 |
| 404 invoke0() { | 412 invoke0() { |
| 405 return guardAsync( | 413 return guardAsync( |
| 406 () { | 414 () { |
| 407 ++_calls; | 415 ++_calls; |
| 408 if (_shouldCallBack()) { | 416 if (_shouldCallBack()) { |
| 409 return _callback(); | 417 return _callback(); |
| 410 } | 418 } |
| 411 }, | 419 }, |
| 412 _after); | 420 _after, _testNum); |
| 413 } | 421 } |
| 414 | 422 |
| 415 invoke1(arg1) { | 423 invoke1(arg1) { |
| 416 return guardAsync( | 424 return guardAsync( |
| 417 () { | 425 () { |
| 418 ++_calls; | 426 ++_calls; |
| 419 if (_shouldCallBack()) { | 427 if (_shouldCallBack()) { |
| 420 return _callback(arg1); | 428 return _callback(arg1); |
| 421 } | 429 } |
| 422 }, | 430 }, |
| 423 _after); | 431 _after, _testNum); |
| 424 } | 432 } |
| 425 | 433 |
| 426 invoke2(arg1, arg2) { | 434 invoke2(arg1, arg2) { |
| 427 return guardAsync( | 435 return guardAsync( |
| 428 () { | 436 () { |
| 429 ++_calls; | 437 ++_calls; |
| 430 if (_shouldCallBack()) { | 438 if (_shouldCallBack()) { |
| 431 return _callback(arg1, arg2); | 439 return _callback(arg1, arg2); |
| 432 } | 440 } |
| 433 }, | 441 }, |
| 434 _after); | 442 _after, _testNum); |
| 435 } | 443 } |
| 436 | 444 |
| 437 /** Returns false if we exceded the number of expected calls. */ | 445 /** Returns false if we exceded the number of expected calls. */ |
| 438 bool _checkCallCount() { | 446 bool _checkCallCount() { |
| 439 if (_calls > _expectedCalls) { | 447 if (_calls > _expectedCalls) { |
| 440 _testCase.error( | 448 _testCase.error( |
| 441 'Callback called more times than expected ' | 449 'Callback called more times than expected ' |
| 442 '($_calls > $_expectedCalls).', | 450 '($_calls > $_expectedCalls).', |
| 443 ''); | 451 ''); |
| 444 _state = _UNCAUGHT_ERROR; | 452 _state = _UNCAUGHT_ERROR; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 520 | 528 |
| 521 /** | 529 /** |
| 522 * Like [expectAsyncUntil0] but [callback] should take 2 positional arguments. | 530 * Like [expectAsyncUntil0] but [callback] should take 2 positional arguments. |
| 523 */ | 531 */ |
| 524 // TODO(sigmund): deprecate this API when issue 2706 is fixed. | 532 // TODO(sigmund): deprecate this API when issue 2706 is fixed. |
| 525 Function expectAsyncUntil2(Function callback, Function isDone) { | 533 Function expectAsyncUntil2(Function callback, Function isDone) { |
| 526 return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke2; | 534 return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke2; |
| 527 } | 535 } |
| 528 | 536 |
| 529 /** | 537 /** |
| 538 * Wraps the [callback] in a new function and returns that function. The new | |
| 539 * function will be able to handle exceptions by directing them to the correct | |
| 540 * test. This is thus similar to expectAsync0. Use it to wrap any callbacks that | |
| 541 * might optionally be called but may never be called during the test. | |
| 542 * [callback] should take between 0 and 4 positional arguments (named arguments | |
| 543 * are not supported). | |
| 544 */ | |
| 545 Function _protectAsync(Function callback) { | |
| 546 return new _SpreadArgsHelper.optionalCalls(callback).invoke; | |
| 547 } | |
| 548 | |
| 549 /** | |
| 550 * Wraps the [callback] in a new function and returns that function. The new | |
| 551 * function will be able to handle exceptions by directing them to the correct | |
| 552 * test. This is thus similar to expectAsync0. Use it to wrap any callbacks that | |
| 553 * might optionally be called but may never be called during the test. | |
| 554 * [callback] should take 0 positional arguments (named arguments are not | |
| 555 * supported). | |
| 556 */ | |
| 557 // TODO(sigmund): deprecate this API when issue 2706 is fixed. | |
| 558 Function protectAsync0(Function callback) { | |
| 559 return new _SpreadArgsHelper.optionalCalls(callback).invoke0; | |
| 560 } | |
| 561 | |
| 562 /** | |
| 563 * Like [protectAsync0] but [callback] should take 1 positional argument. | |
| 564 */ | |
| 565 // TODO(sigmund): deprecate this API when issue 2706 is fixed. | |
| 566 Function protectAsync1(Function callback) { | |
| 567 return new _SpreadArgsHelper.optionalCalls(callback).invoke1; | |
| 568 } | |
| 569 | |
| 570 /** | |
| 571 * Like [protectAsync0] but [callback] should take 2 positional arguments. | |
| 572 */ | |
| 573 // TODO(sigmund): deprecate this API when issue 2706 is fixed. | |
| 574 Function protectAsync2(Function callback) { | |
| 575 return new _SpreadArgsHelper.optionalCalls(callback).invoke2; | |
| 576 } | |
| 577 | |
| 578 /** | |
| 530 * Creates a new named group of tests. Calls to group() or test() within the | 579 * Creates a new named group of tests. Calls to group() or test() within the |
| 531 * body of the function passed to this will inherit this group's description. | 580 * body of the function passed to this will inherit this group's description. |
| 532 */ | 581 */ |
| 533 void group(String description, void body()) { | 582 void group(String description, void body()) { |
| 534 ensureInitialized(); | 583 ensureInitialized(); |
| 535 | 584 |
| 536 // Concatenate the new group. | 585 // Concatenate the new group. |
| 537 final parentGroup = _currentGroup; | 586 final parentGroup = _currentGroup; |
| 538 if (_currentGroup != '') { | 587 if (_currentGroup != '') { |
| 539 // Add a space. | 588 // Add a space. |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 682 for (var i = 0; i < _tests.length; i++) { | 731 for (var i = 0; i < _tests.length; i++) { |
| 683 _tests[i].callbacks = 0; // Note - won't work with old asyncTests. | 732 _tests[i].callbacks = 0; // Note - won't work with old asyncTests. |
| 684 } | 733 } |
| 685 runTests(); | 734 runTests(); |
| 686 } | 735 } |
| 687 | 736 |
| 688 /** | 737 /** |
| 689 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, update | 738 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, update |
| 690 * the [_currentTest] status accordingly. | 739 * the [_currentTest] status accordingly. |
| 691 */ | 740 */ |
| 692 guardAsync(tryBody, [finallyBody]) { | 741 guardAsync(tryBody, [finallyBody, testNum = -1]) { |
| 742 if (testNum < 0) testNum = _currentTest; | |
| 693 try { | 743 try { |
| 694 return tryBody(); | 744 return tryBody(); |
| 695 } catch (var e, var trace) { | 745 } catch (var e, var trace) { |
| 696 registerException(e, trace); | 746 registerException(testNum, e, trace); |
| 697 } finally { | 747 } finally { |
| 698 _state = _READY; | 748 _state = _READY; |
| 699 if (finallyBody != null) finallyBody(); | 749 if (finallyBody != null) finallyBody(); |
| 700 } | 750 } |
| 701 } | 751 } |
| 702 | 752 |
| 703 /** | 753 /** |
| 704 * Registers that an exception was caught for the current test. | 754 * Registers that an exception was caught for the current test. |
| 705 */ | 755 */ |
| 706 registerException(e, [trace]) { | 756 registerException(testNum, e, [trace]) { |
| 707 if (e is ExpectException) { | 757 if (_tests[testNum].result == null) { |
| 708 Expect.isTrue(_currentTest < _tests.length); | 758 if (e is ExpectException) { |
| 709 if (_state != _UNCAUGHT_ERROR) { | 759 _tests[testNum].fail(e.message, trace == null ? '' : trace.toString()); |
| 710 _tests[_currentTest].fail(e.message, | 760 } else { |
| 711 trace == null ? '' : trace.toString()); | 761 _tests[testNum].fail('Caught $e', trace == null ? '' : trace.toString()); |
| 712 } | 762 } |
| 713 } else { | 763 } else { |
| 714 if (_state == _RUNNING_TEST) { | 764 _tests[testNum].error('Caught $e', trace == null ? '' : trace.toString()); |
| 715 // If a random exception is thrown from within a test, we consider that | |
| 716 // a test failure too. A test case implicitly has an expectation that it | |
| 717 // will run to completion without an uncaught exception being thrown. | |
| 718 _tests[_currentTest].fail('Caught $e', | |
| 719 trace == null ? '' : trace.toString()); | |
| 720 } else if (_state != _UNCAUGHT_ERROR) { | |
| 721 _tests[_currentTest].error('Caught $e', | |
| 722 trace == null ? '' : trace.toString()); | |
| 723 } | |
| 724 } | 765 } |
| 725 _nextTestCase(); | 766 if (testNum == _currentTest) { |
|
Siggi Cherem (dart-lang)
2012/08/02 00:19:07
yay!
gram
2012/08/02 00:41:32
Done.
| |
| 767 _nextTestCase(); | |
| 768 } | |
| 726 } | 769 } |
| 727 | 770 |
| 728 /** | 771 /** |
| 729 * Runs a batch of tests, yielding whenever an asynchronous test starts | 772 * Runs a batch of tests, yielding whenever an asynchronous test starts |
| 730 * running. Tests will resume executing when such asynchronous test calls | 773 * running. Tests will resume executing when such asynchronous test calls |
| 731 * [done] or if it fails with an exception. | 774 * [done] or if it fails with an exception. |
| 732 */ | 775 */ |
| 733 _nextBatch() { | 776 _nextBatch() { |
| 734 while (_currentTest < _tests.length) { | 777 while (_currentTest < _tests.length) { |
| 735 final testCase = _tests[_currentTest]; | 778 final testCase = _tests[_currentTest]; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 833 } | 876 } |
| 834 | 877 |
| 835 /** Enable a test by ID. */ | 878 /** Enable a test by ID. */ |
| 836 void enableTest(int testId) => _setTestEnabledState(testId, true); | 879 void enableTest(int testId) => _setTestEnabledState(testId, true); |
| 837 | 880 |
| 838 /** Disable a test by ID. */ | 881 /** Disable a test by ID. */ |
| 839 void disableTest(int testId) => _setTestEnabledState(testId, false); | 882 void disableTest(int testId) => _setTestEnabledState(testId, false); |
| 840 | 883 |
| 841 /** Signature for a test function. */ | 884 /** Signature for a test function. */ |
| 842 typedef void TestFunction(); | 885 typedef void TestFunction(); |
| OLD | NEW |