| 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, use the pub package manager. | 8 * To import this library, use the pub package manager. |
| 9 * Create a pubspec.yaml file in your project and add | 9 * Create a pubspec.yaml file in your project and add |
| 10 * a dependency on unittest with the following lines: | 10 * a dependency on unittest with the following lines: |
| 11 * dependencies: | 11 * dependencies: |
| 12 * unittest: | 12 * unittest: |
| 13 * sdk: unittest | 13 * sdk: unittest |
| 14 * | 14 * |
| 15 * Then run 'pub install' from your project directory or using | 15 * Then run 'pub install' from your project directory or using |
| 16 * the DartEditor. | 16 * the DartEditor. |
| 17 * | 17 * |
| 18 * Please see [Pub Getting Started](http://pub.dartlang.org/doc) | 18 * Please see [Pub Getting Started](http://pub.dartlang.org/doc) |
| 19 * for more details about the pub package manager. | 19 * for more details about the pub package manager. |
| 20 * | 20 * |
| 21 * ##Concepts## | 21 * ##Concepts## |
| 22 * | 22 * |
| 23 * * Tests: Tests are specified via the top-level function [test], they can be | 23 * * Tests: Tests are specified via the top-level function [test], they can be |
| 24 * organized together using [group]. | 24 * organized together using [group]. |
| 25 * * Checks: Test expectations can be specified via [expect] | 25 * * Checks: Test expectations can be specified via [expect] |
| 26 * * Matchers: [expect] assertions are written declaratively using [Matcher]s | 26 * * Matchers: [expect] assertions are written declaratively using [Matcher]s |
| 27 * * Configuration: The framework can be adapted by calling [configure] with a | 27 * * Configuration: The framework can be adapted by calling [configure] with a |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 * // indicate that the asynchronous callback was invoked. | 141 * // indicate that the asynchronous callback was invoked. |
| 142 * async.complete(); | 142 * async.complete(); |
| 143 * }); | 143 * }); |
| 144 * }); | 144 * }); |
| 145 * } | 145 * } |
| 146 * | 146 * |
| 147 */ | 147 */ |
| 148 library unittest; | 148 library unittest; |
| 149 | 149 |
| 150 import 'dart:isolate'; | 150 import 'dart:isolate'; |
| 151 import 'matcher.dart'; |
| 152 export 'matcher.dart'; |
| 151 | 153 |
| 152 part 'collection_matchers.dart'; | 154 part 'src/config.dart'; |
| 153 part 'config.dart'; | 155 part 'src/test_case.dart'; |
| 154 part 'core_matchers.dart'; | |
| 155 part 'description.dart'; | |
| 156 part 'expect.dart'; | |
| 157 part 'future_matchers.dart'; | |
| 158 part 'interfaces.dart'; | |
| 159 part 'map_matchers.dart'; | |
| 160 part 'matcher.dart'; | |
| 161 part 'mock.dart'; | |
| 162 part 'numeric_matchers.dart'; | |
| 163 part 'operator_matchers.dart'; | |
| 164 part 'string_matchers.dart'; | |
| 165 part 'test_case.dart'; | |
| 166 | 156 |
| 167 /** [Configuration] used by the unittest library. */ | 157 /** [Configuration] used by the unittest library. */ |
| 168 Configuration _config = null; | 158 Configuration _config = null; |
| 169 | 159 |
| 170 Configuration get config => _config; | 160 Configuration get config => _config; |
| 171 | 161 |
| 172 /** | 162 /** |
| 173 * Set the [Configuration] used by the unittest library. Returns any | 163 * Set the [Configuration] used by the unittest library. Returns any |
| 174 * previous configuration. | 164 * previous configuration. |
| 175 * TODO: consider deprecating in favor of a setter now we have a getter. | 165 * TODO: consider deprecating in favor of a setter now we have a getter. |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 _SpreadArgsHelper.variableCallCount(callback, isDone) { | 360 _SpreadArgsHelper.variableCallCount(callback, isDone) { |
| 371 _init(callback, _always, isDone, 1); | 361 _init(callback, _always, isDone, 1); |
| 372 } | 362 } |
| 373 | 363 |
| 374 _SpreadArgsHelper.optionalCalls(callback) { | 364 _SpreadArgsHelper.optionalCalls(callback) { |
| 375 _init(callback, _always, () => false, 0); | 365 _init(callback, _always, () => false, 0); |
| 376 } | 366 } |
| 377 | 367 |
| 378 _after() { | 368 _after() { |
| 379 if (_isDone()) { | 369 if (_isDone()) { |
| 380 _handleCallbackFunctionComplete(); | 370 _handleCallbackFunctionComplete(_testNum); |
| 381 } | 371 } |
| 382 } | 372 } |
| 383 | 373 |
| 384 _allCallsDone() => _actualCalls == _expectedCalls; | 374 _allCallsDone() => _actualCalls == _expectedCalls; |
| 385 | 375 |
| 386 _always() { | 376 _always() { |
| 387 // Always run except if the test is done. | 377 // Always run except if the test is done. |
| 388 if (_testCase.isComplete) { | 378 if (_testCase.isComplete) { |
| 389 _testCase.error( | 379 _testCase.error( |
| 390 'Callback called after already being marked as done ($_actualCalls).', | 380 'Callback called after already being marked as done ($_actualCalls).', |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 639 * calls to [test]. | 629 * calls to [test]. |
| 640 */ | 630 */ |
| 641 void tearDown(Function teardownTest) { | 631 void tearDown(Function teardownTest) { |
| 642 _testTeardown = teardownTest; | 632 _testTeardown = teardownTest; |
| 643 } | 633 } |
| 644 | 634 |
| 645 /** | 635 /** |
| 646 * Called when one of the callback functions is done with all expected | 636 * Called when one of the callback functions is done with all expected |
| 647 * calls. | 637 * calls. |
| 648 */ | 638 */ |
| 649 void _handleCallbackFunctionComplete() { | 639 void _handleCallbackFunctionComplete(testNum) { |
| 650 // TODO (gram): we defer this to give the nextBatch recursive | 640 // TODO (gram): we defer this to give the nextBatch recursive |
| 651 // stack a chance to unwind. This is a temporary hack but | 641 // stack a chance to unwind. This is a temporary hack but |
| 652 // really a bunch of code here needs to be fixed. We have a | 642 // really a bunch of code here needs to be fixed. We have a |
| 653 // single array that is being iterated through by nextBatch(), | 643 // single array that is being iterated through by nextBatch(), |
| 654 // which is recursively invoked in the case of async tests that | 644 // which is recursively invoked in the case of async tests that |
| 655 // run synchronously. Bad things can then happen. | 645 // run synchronously. Bad things can then happen. |
| 656 _defer(() { | 646 _defer(() { |
| 647 if (_currentTest != testNum) { |
| 648 if (_tests[testNum].result == PASS) { |
| 649 _tests[testNum].error("Unexpected extra callbacks", ''); |
| 650 } |
| 651 return; // Extraneous callback. |
| 652 } |
| 657 if (_currentTest < _tests.length) { | 653 if (_currentTest < _tests.length) { |
| 658 final testCase = _tests[_currentTest]; | 654 final testCase = _tests[_currentTest]; |
| 659 --testCase.callbackFunctionsOutstanding; | 655 --testCase.callbackFunctionsOutstanding; |
| 660 if (testCase.callbackFunctionsOutstanding < 0) { | 656 if (testCase.callbackFunctionsOutstanding < 0) { |
| 661 // TODO(gram): Check: Can this even happen? | 657 // TODO(gram): Check: Can this even happen? |
| 662 testCase.error( | 658 testCase.error( |
| 663 'More calls to _handleCallbackFunctionComplete() than expected.', | 659 'More calls to _handleCallbackFunctionComplete() than expected.', |
| 664 ''); | 660 ''); |
| 665 } else if (testCase.callbackFunctionsOutstanding == 0) { | 661 } else if (testCase.callbackFunctionsOutstanding == 0) { |
| 666 if (!testCase.isComplete) { | 662 if (!testCase.isComplete) { |
| 667 testCase.pass(); | 663 testCase.pass(); |
| 668 } | 664 } |
| 669 _nextTestCase(); | 665 _nextTestCase(); |
| 670 } | 666 } |
| 671 } | 667 } |
| 672 }); | 668 }); |
| 673 } | 669 } |
| 674 | 670 |
| 675 /** Advance to the next test case. */ | 671 /** Advance to the next test case. */ |
| 676 void _nextTestCase() { | 672 void _nextTestCase() { |
| 677 _currentTest++; | 673 _currentTest++; |
| 678 _testRunner(); | 674 _testRunner(); |
| 679 } | 675 } |
| 680 | 676 |
| 681 /** | 677 /** |
| 682 * Temporary hack: expose old API. | 678 * Temporary hack: expose old API. |
| 683 * TODO(gram) remove this when WebKit tests are working with new framework | 679 * TODO(gram) remove this when WebKit tests are working with new framework |
| 684 */ | 680 */ |
| 685 void callbackDone() { | 681 void callbackDone() { |
| 686 _handleCallbackFunctionComplete(); | 682 _handleCallbackFunctionComplete(_currentTest); |
| 687 } | 683 } |
| 688 | 684 |
| 689 /** | 685 /** |
| 690 * Utility function that can be used to notify the test framework that an | 686 * Utility function that can be used to notify the test framework that an |
| 691 * error was caught outside of this library. | 687 * error was caught outside of this library. |
| 692 */ | 688 */ |
| 693 void _reportTestError(String msg, String trace) { | 689 void _reportTestError(String msg, String trace) { |
| 694 if (_currentTest < _tests.length) { | 690 if (_currentTest < _tests.length) { |
| 695 final testCase = _tests[_currentTest]; | 691 final testCase = _tests[_currentTest]; |
| 696 testCase.error(msg, trace); | 692 testCase.error(msg, trace); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 847 } | 843 } |
| 848 | 844 |
| 849 /** | 845 /** |
| 850 * Lazily initializes the test library if not already initialized. | 846 * Lazily initializes the test library if not already initialized. |
| 851 */ | 847 */ |
| 852 ensureInitialized() { | 848 ensureInitialized() { |
| 853 if (_initialized) { | 849 if (_initialized) { |
| 854 return; | 850 return; |
| 855 } | 851 } |
| 856 _initialized = true; | 852 _initialized = true; |
| 853 // Hook our async guard into the matcher library. |
| 854 wrapAsync = expectAsync1; |
| 857 | 855 |
| 858 _tests = <TestCase>[]; | 856 _tests = <TestCase>[]; |
| 859 _testRunner = _nextBatch; | 857 _testRunner = _nextBatch; |
| 860 _uncaughtErrorMessage = null; | 858 _uncaughtErrorMessage = null; |
| 861 | 859 |
| 862 if (_config == null) { | 860 if (_config == null) { |
| 863 _config = new Configuration(); | 861 _config = new Configuration(); |
| 864 } | 862 } |
| 865 _config.onInit(); | 863 _config.onInit(); |
| 866 | 864 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 897 } | 895 } |
| 898 | 896 |
| 899 /** Enable a test by ID. */ | 897 /** Enable a test by ID. */ |
| 900 void enableTest(int testId) => _setTestEnabledState(testId, true); | 898 void enableTest(int testId) => _setTestEnabledState(testId, true); |
| 901 | 899 |
| 902 /** Disable a test by ID. */ | 900 /** Disable a test by ID. */ |
| 903 void disableTest(int testId) => _setTestEnabledState(testId, false); | 901 void disableTest(int testId) => _setTestEnabledState(testId, false); |
| 904 | 902 |
| 905 /** Signature for a test function. */ | 903 /** Signature for a test function. */ |
| 906 typedef void TestFunction(); | 904 typedef void TestFunction(); |
| OLD | NEW |