Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 * ## Installing ## | 8 * ## Installing ## |
| 9 * | 9 * |
| 10 * Use [pub][] to install this package. Add the following to your `pubspec.yaml` | 10 * Use [pub][] to install this package. Add the following to your `pubspec.yaml` |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 207 | 207 |
| 208 /** Separator used between group names and test names. */ | 208 /** Separator used between group names and test names. */ |
| 209 String groupSep = ' '; | 209 String groupSep = ' '; |
| 210 | 210 |
| 211 final List<TestCase> _testCases = new List<TestCase>(); | 211 final List<TestCase> _testCases = new List<TestCase>(); |
| 212 | 212 |
| 213 /** Tests executed in this suite. */ | 213 /** Tests executed in this suite. */ |
| 214 final List<TestCase> testCases = new UnmodifiableListView<TestCase>(_testCases); | 214 final List<TestCase> testCases = new UnmodifiableListView<TestCase>(_testCases); |
| 215 | 215 |
| 216 /** | 216 /** |
| 217 * The set of tests to run can be restricted by using soloTest and soloGroup. | |
| 218 * As groups can be nested we use a counter to keep track of the nest level | |
| 219 * of soloing. We use -1 to indicate that there are no solo tests. | |
| 220 */ | |
| 221 int _solo_level = -1; | |
| 222 | |
| 223 /** | |
| 217 * Setup and teardown functions for a group and its parents, the latter | 224 * Setup and teardown functions for a group and its parents, the latter |
| 218 * for chaining. | 225 * for chaining. |
| 219 */ | 226 */ |
| 220 class GroupContext { | 227 class GroupContext { |
| 221 final GroupContext parent; | 228 final GroupContext parent; |
| 222 | 229 |
| 223 /** Description text of the current test group. */ | 230 /** Description text of the current test group. */ |
| 224 final String _name; | 231 final String _name; |
| 225 | 232 |
| 226 /** Setup function called before each test in a group. */ | 233 /** Setup function called before each test in a group. */ |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 300 | 307 |
| 301 /** Test case result strings. */ | 308 /** Test case result strings. */ |
| 302 // TODO(gram) we should change these constants to use a different string | 309 // TODO(gram) we should change these constants to use a different string |
| 303 // (so that writing 'FAIL' in the middle of a test doesn't | 310 // (so that writing 'FAIL' in the middle of a test doesn't |
| 304 // imply that the test fails). We can't do it without also changing | 311 // imply that the test fails). We can't do it without also changing |
| 305 // the testrunner and test.dart though. | 312 // the testrunner and test.dart though. |
| 306 const PASS = 'pass'; | 313 const PASS = 'pass'; |
| 307 const FAIL = 'fail'; | 314 const FAIL = 'fail'; |
| 308 const ERROR = 'error'; | 315 const ERROR = 'error'; |
| 309 | 316 |
| 310 /** If set, then all other test cases will be ignored. */ | |
| 311 TestCase _soloTest; | |
| 312 | |
| 313 /** | 317 /** |
| 314 * A map that can be used to communicate state between a test driver | 318 * A map that can be used to communicate state between a test driver |
| 315 * or main() function and the tests, particularly when these two | 319 * or main() function and the tests, particularly when these two |
| 316 * are otherwise independent. For example, a test driver that starts | 320 * are otherwise independent. For example, a test driver that starts |
| 317 * an HTTP server and then runs tests that access that server could use | 321 * an HTTP server and then runs tests that access that server could use |
| 318 * this as a way of communicating the server port to the tests. | 322 * this as a way of communicating the server port to the tests. |
| 319 */ | 323 */ |
| 320 Map testState = {}; | 324 Map testState = {}; |
| 321 | 325 |
| 322 /** | 326 /** |
| 323 * Creates a new test case with the given description and body. The | 327 * Creates a new test case with the given description and body. The |
| 324 * description will include the descriptions of any surrounding group() | 328 * description will include the descriptions of any surrounding group() |
| 325 * calls. | 329 * calls. |
| 326 */ | 330 */ |
| 327 void test(String spec, TestFunction body) { | 331 void test(String spec, TestFunction body) { |
| 328 ensureInitialized(); | 332 ensureInitialized(); |
| 329 _testCases.add(new TestCase._internal(testCases.length + 1, _fullSpec(spec), | 333 if (_solo_level != 0) { |
| 330 body)); | 334 var testcase = new TestCase._internal(testCases.length + 1, _fullSpec(spec), |
| 335 body); | |
| 336 _testCases.add(testcase); | |
| 337 } | |
| 331 } | 338 } |
| 332 | 339 |
| 340 /** Convenience function for skipping a test. */ | |
| 341 void skip_test(String spec, TestFunction body){} | |
| 342 | |
| 333 /** | 343 /** |
| 334 * Creates a new test case with the given description and body. The | 344 * Creates a new test case with the given description and body. The |
| 335 * description will include the descriptions of any surrounding group() | 345 * description will include the descriptions of any surrounding group() |
| 336 * calls. | 346 * calls. |
| 337 * | 347 * |
| 338 * "solo_" means that this will be the only test that is run. All other tests | 348 * If we use [solo_test] (or [solo_group]) instead of test, then all non-solo |
| 339 * will be skipped. This is a convenience function to let you quickly isolate | 349 * tests will be disabled. Note that if we use [solo_group], all tests in |
| 340 * a single test by adding "solo_" before it to temporarily disable all other | 350 * the group will be enabled, regardless of whether they use [test] or |
| 341 * tests. | 351 * [skip_test], or whether they are in a nested [group] vs [solo_group]. Put |
| 352 * another way, if there are any calls to [solo_test] or [solo_group] in a test | |
| 353 * file, all tests that are not inside a [solo_group] will be disabled unless | |
| 354 * they are [solo_test]s. | |
| 355 * | |
| 356 * [skip_test] and [skip_group] take precedence over soloing, by virtue of the | |
| 357 * fact that they are effectively no-ops. | |
| 342 */ | 358 */ |
| 343 void solo_test(String spec, TestFunction body) { | 359 void solo_test(String spec, TestFunction body) { |
| 344 // TODO(rnystrom): Support multiple solos. If more than one test is solo-ed, | 360 ensureInitialized(); |
| 345 // all of the solo-ed tests and none of the non-solo-ed ones should run. | 361 if (_solo_level < 0) { |
| 346 if (_soloTest != null) { | 362 _solo_level = 0; |
| 347 throw new Exception('Only one test can be soloed right now.'); | 363 // This is the first solo-ed test. Discard all tests up to now. |
| 364 _testCases.clear(); | |
| 348 } | 365 } |
| 349 | 366 ++_solo_level; |
| 350 ensureInitialized(); | 367 test(spec, body); |
|
kevmoo-old
2013/04/25 21:56:34
DBR: try...finally?
gram
2013/04/25 22:01:16
Done.
| |
| 351 | 368 --_solo_level; |
| 352 _soloTest = new TestCase._internal(testCases.length + 1, _fullSpec(spec), | |
| 353 body); | |
| 354 _testCases.add(_soloTest); | |
| 355 } | 369 } |
| 356 | 370 |
| 357 /** Sentinel value for [_SpreadArgsHelper]. */ | 371 /** Sentinel value for [_SpreadArgsHelper]. */ |
| 358 class _Sentinel { | 372 class _Sentinel { |
| 359 const _Sentinel(); | 373 const _Sentinel(); |
| 360 } | 374 } |
| 361 | 375 |
| 362 /** Simulates spread arguments using named arguments. */ | 376 /** Simulates spread arguments using named arguments. */ |
| 363 // TODO(sigmund): remove this class and simply use a closure with named | 377 // TODO(sigmund): remove this class and simply use a closure with named |
| 364 // arguments (if still applicable). | 378 // arguments (if still applicable). |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 588 body(); | 602 body(); |
| 589 } catch (e, trace) { | 603 } catch (e, trace) { |
| 590 var stack = (trace == null) ? '' : ': ${trace.toString()}'; | 604 var stack = (trace == null) ? '' : ': ${trace.toString()}'; |
| 591 _uncaughtErrorMessage = "${e.toString()}$stack"; | 605 _uncaughtErrorMessage = "${e.toString()}$stack"; |
| 592 } finally { | 606 } finally { |
| 593 // Now that the group is over, restore the previous one. | 607 // Now that the group is over, restore the previous one. |
| 594 _currentContext = _currentContext.parent; | 608 _currentContext = _currentContext.parent; |
| 595 } | 609 } |
| 596 } | 610 } |
| 597 | 611 |
| 612 /** Like [skip_test], but for groups. */ | |
| 613 void skip_group(String description, void body()) {} | |
| 614 | |
| 615 /** Like [solo_test], but for groups. */ | |
| 616 void solo_group(String description, void body()) { | |
| 617 ensureInitialized(); | |
| 618 if (_solo_level < 0) { | |
| 619 _solo_level = 0; | |
| 620 // This is the first solo-ed group. Discard all tests up to now. | |
| 621 _testCases.clear(); | |
| 622 } | |
| 623 ++_solo_level; | |
| 624 group(description, body); | |
|
kevmoo-old
2013/04/25 21:56:34
DBR: try...finally?
gram
2013/04/25 22:01:16
Done.
| |
| 625 --_solo_level; | |
| 626 } | |
| 627 | |
| 598 /** | 628 /** |
| 599 * Register a [setUp] function for a test [group]. This function will | 629 * Register a [setUp] function for a test [group]. This function will |
| 600 * be called before each test in the group is run. | 630 * be called before each test in the group is run. |
| 601 * [setUp] and [tearDown] should be called within the [group] before any | 631 * [setUp] and [tearDown] should be called within the [group] before any |
| 602 * calls to [test]. The [setupTest] function can be asynchronous; in this | 632 * calls to [test]. The [setupTest] function can be asynchronous; in this |
| 603 * case it must return a [Future]. | 633 * case it must return a [Future]. |
| 604 */ | 634 */ |
| 605 void setUp(Function setupTest) { | 635 void setUp(Function setupTest) { |
| 606 _currentContext.testSetup = setupTest; | 636 _currentContext.testSetup = setupTest; |
| 607 } | 637 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 661 filterFunction = testFilter; | 691 filterFunction = testFilter; |
| 662 } | 692 } |
| 663 _testCases.retainWhere(filterFunction); | 693 _testCases.retainWhere(filterFunction); |
| 664 } | 694 } |
| 665 | 695 |
| 666 /** Runs all queued tests, one at a time. */ | 696 /** Runs all queued tests, one at a time. */ |
| 667 void runTests() { | 697 void runTests() { |
| 668 _ensureInitialized(false); | 698 _ensureInitialized(false); |
| 669 _currentTestCaseIndex = 0; | 699 _currentTestCaseIndex = 0; |
| 670 | 700 |
| 671 // If we are soloing a test, remove all the others. | |
| 672 if (_soloTest != null) { | |
| 673 filterTests((t) => t == _soloTest); | |
| 674 } | |
| 675 | |
| 676 _config.onStart(); | 701 _config.onStart(); |
| 677 | 702 |
| 678 runAsync(() { | 703 runAsync(() { |
| 679 _nextBatch(); | 704 _nextBatch(); |
| 680 }); | 705 }); |
| 681 } | 706 } |
| 682 | 707 |
| 683 /** | 708 /** |
| 684 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, it is | 709 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, it is |
| 685 * passed to the corresponding test. | 710 * passed to the corresponding test. |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 796 // Immediately queue the suite up. It will run after a timeout (i.e. after | 821 // Immediately queue the suite up. It will run after a timeout (i.e. after |
| 797 // main() has returned). | 822 // main() has returned). |
| 798 runAsync(runTests); | 823 runAsync(runTests); |
| 799 } | 824 } |
| 800 } | 825 } |
| 801 | 826 |
| 802 /** Select a solo test by ID. */ | 827 /** Select a solo test by ID. */ |
| 803 void setSoloTest(int id) { | 828 void setSoloTest(int id) { |
| 804 for (var i = 0; i < testCases.length; i++) { | 829 for (var i = 0; i < testCases.length; i++) { |
| 805 if (testCases[i].id == id) { | 830 if (testCases[i].id == id) { |
| 806 _soloTest = testCases[i]; | 831 var testCase = testCases[i]; |
| 832 _testCases.clear(); | |
| 833 _testCases.add(testCase); | |
| 807 break; | 834 break; |
| 808 } | 835 } |
| 809 } | 836 } |
| 810 } | 837 } |
| 811 | 838 |
| 812 /** Enable/disable a test by ID. */ | 839 /** Enable/disable a test by ID. */ |
| 813 void _setTestEnabledState(int testId, bool state) { | 840 void _setTestEnabledState(int testId, bool state) { |
| 814 // Try fast path first. | 841 // Try fast path first. |
| 815 if (testCases.length > testId && testCases[testId].id == testId) { | 842 if (testCases.length > testId && testCases[testId].id == testId) { |
| 816 testCases[testId].enabled = state; | 843 testCases[testId].enabled = state; |
| 817 } else { | 844 } else { |
| 818 for (var i = 0; i < testCases.length; i++) { | 845 for (var i = 0; i < testCases.length; i++) { |
| 819 if (testCases[i].id == testId) { | 846 if (testCases[i].id == testId) { |
| 820 testCases[i].enabled = state; | 847 testCases[i].enabled = state; |
| 821 break; | 848 break; |
| 822 } | 849 } |
| 823 } | 850 } |
| 824 } | 851 } |
| 825 } | 852 } |
| 826 | 853 |
| 827 /** Enable a test by ID. */ | 854 /** Enable a test by ID. */ |
| 828 void enableTest(int testId) => _setTestEnabledState(testId, true); | 855 void enableTest(int testId) => _setTestEnabledState(testId, true); |
| 829 | 856 |
| 830 /** Disable a test by ID. */ | 857 /** Disable a test by ID. */ |
| 831 void disableTest(int testId) => _setTestEnabledState(testId, false); | 858 void disableTest(int testId) => _setTestEnabledState(testId, false); |
| 832 | 859 |
| 833 /** Signature for a test function. */ | 860 /** Signature for a test function. */ |
| 834 typedef dynamic TestFunction(); | 861 typedef dynamic TestFunction(); |
| OLD | NEW |