| 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 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 } | 360 } |
| 361 | 361 |
| 362 /** Simulates spread arguments using named arguments. */ | 362 /** Simulates spread arguments using named arguments. */ |
| 363 // TODO(sigmund): remove this class and simply use a closure with named | 363 // TODO(sigmund): remove this class and simply use a closure with named |
| 364 // arguments (if still applicable). | 364 // arguments (if still applicable). |
| 365 class _SpreadArgsHelper { | 365 class _SpreadArgsHelper { |
| 366 final Function callback; | 366 final Function callback; |
| 367 final int minExpectedCalls; | 367 final int minExpectedCalls; |
| 368 final int maxExpectedCalls; | 368 final int maxExpectedCalls; |
| 369 final Function isDone; | 369 final Function isDone; |
| 370 final int testNum; | |
| 371 final String id; | 370 final String id; |
| 372 int actualCalls = 0; | 371 int actualCalls = 0; |
| 373 TestCase testCase; | 372 final TestCase testCase; |
| 374 bool complete; | 373 bool complete; |
| 375 static const sentinel = const _Sentinel(); | 374 static const sentinel = const _Sentinel(); |
| 376 | 375 |
| 377 _SpreadArgsHelper(Function callback, int minExpected, int maxExpected, | 376 _SpreadArgsHelper(Function callback, int minExpected, int maxExpected, |
| 378 Function isDone, String id) | 377 Function isDone, String id) |
| 379 : this.callback = callback, | 378 : this.callback = callback, |
| 380 minExpectedCalls = minExpected, | 379 minExpectedCalls = minExpected, |
| 381 maxExpectedCalls = (maxExpected == 0 && minExpected > 0) | 380 maxExpectedCalls = (maxExpected == 0 && minExpected > 0) |
| 382 ? minExpected | 381 ? minExpected |
| 383 : maxExpected, | 382 : maxExpected, |
| 384 this.isDone = isDone, | 383 this.isDone = isDone, |
| 385 testNum = _currentTestCaseIndex, | 384 this.testCase = currentTestCase, |
| 386 this.id = _makeCallbackId(id, callback) { | 385 this.id = _makeCallbackId(id, callback) { |
| 387 ensureInitialized(); | 386 ensureInitialized(); |
| 388 if (!(_currentTestCaseIndex >= 0 && | 387 if (testCase == null) { |
| 389 _currentTestCaseIndex < testCases.length && | |
| 390 testCases[_currentTestCaseIndex] != null)) { | |
| 391 print("No valid test, did you forget to run your test inside a call " | 388 print("No valid test, did you forget to run your test inside a call " |
| 392 "to test()?"); | 389 "to test()?"); |
| 393 } | 390 } |
| 394 assert(_currentTestCaseIndex >= 0 && | 391 assert(testCase != null); |
| 395 _currentTestCaseIndex < testCases.length && | 392 |
| 396 testCases[_currentTestCaseIndex] != null); | |
| 397 testCase = testCases[_currentTestCaseIndex]; | |
| 398 if (isDone != null || minExpected > 0) { | 393 if (isDone != null || minExpected > 0) { |
| 399 testCase._callbackFunctionsOutstanding++; | 394 testCase._callbackFunctionsOutstanding++; |
| 400 complete = false; | 395 complete = false; |
| 401 } else { | 396 } else { |
| 402 complete = true; | 397 complete = true; |
| 403 } | 398 } |
| 404 } | 399 } |
| 405 | 400 |
| 406 static _makeCallbackId(String id, Function callback) { | 401 static _makeCallbackId(String id, Function callback) { |
| 407 // Try to create a reasonable id. | 402 // Try to create a reasonable id. |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 return callback(arg0, arg1, arg2); | 466 return callback(arg0, arg1, arg2); |
| 472 } else if (arg4 == sentinel) { | 467 } else if (arg4 == sentinel) { |
| 473 return callback(arg0, arg1, arg2, arg3); | 468 return callback(arg0, arg1, arg2, arg3); |
| 474 } else { | 469 } else { |
| 475 testCase.error( | 470 testCase.error( |
| 476 'unittest lib does not support callbacks with more than' | 471 'unittest lib does not support callbacks with more than' |
| 477 ' 4 arguments.', | 472 ' 4 arguments.', |
| 478 ''); | 473 ''); |
| 479 } | 474 } |
| 480 }, | 475 }, |
| 481 after, testNum); | 476 after, testCase); |
| 482 } | 477 } |
| 483 | 478 |
| 484 invoke0() { | 479 invoke0() { |
| 485 return _guardAsync( | 480 return _guardAsync( |
| 486 () { | 481 () { |
| 487 if (shouldCallBack()) { | 482 if (shouldCallBack()) { |
| 488 return callback(); | 483 return callback(); |
| 489 } | 484 } |
| 490 }, | 485 }, |
| 491 after, testNum); | 486 after, testCase); |
| 492 } | 487 } |
| 493 | 488 |
| 494 invoke1(arg1) { | 489 invoke1(arg1) { |
| 495 return _guardAsync( | 490 return _guardAsync( |
| 496 () { | 491 () { |
| 497 if (shouldCallBack()) { | 492 if (shouldCallBack()) { |
| 498 return callback(arg1); | 493 return callback(arg1); |
| 499 } | 494 } |
| 500 }, | 495 }, |
| 501 after, testNum); | 496 after, testCase); |
| 502 } | 497 } |
| 503 | 498 |
| 504 invoke2(arg1, arg2) { | 499 invoke2(arg1, arg2) { |
| 505 return _guardAsync( | 500 return _guardAsync( |
| 506 () { | 501 () { |
| 507 if (shouldCallBack()) { | 502 if (shouldCallBack()) { |
| 508 return callback(arg1, arg2); | 503 return callback(arg1, arg2); |
| 509 } | 504 } |
| 510 }, | 505 }, |
| 511 after, testNum); | 506 after, testCase); |
| 512 } | 507 } |
| 513 } | 508 } |
| 514 | 509 |
| 515 /** | 510 /** |
| 516 * Indicate that [callback] is expected to be called a [count] number of times | 511 * Indicate that [callback] is expected to be called a [count] number of times |
| 517 * (by default 1). The unittest framework will wait for the callback to run the | 512 * (by default 1). The unittest framework will wait for the callback to run the |
| 518 * specified [count] times before it continues with the following test. Using | 513 * specified [count] times before it continues with the following test. Using |
| 519 * [_expectAsync] will also ensure that errors that occur within [callback] are | 514 * [_expectAsync] will also ensure that errors that occur within [callback] are |
| 520 * tracked and reported. [callback] should take between 0 and 4 positional | 515 * tracked and reported. [callback] should take between 0 and 4 positional |
| 521 * arguments (named arguments are not supported here). [id] can be used | 516 * arguments (named arguments are not supported here). [id] can be used |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 }); | 761 }); |
| 767 } | 762 } |
| 768 | 763 |
| 769 /** | 764 /** |
| 770 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, it is | 765 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, it is |
| 771 * passed to the corresponding test. | 766 * passed to the corresponding test. |
| 772 * | 767 * |
| 773 * The value returned by [tryBody] (if any) is returned by [guardAsync]. | 768 * The value returned by [tryBody] (if any) is returned by [guardAsync]. |
| 774 */ | 769 */ |
| 775 guardAsync(Function tryBody) { | 770 guardAsync(Function tryBody) { |
| 776 return _guardAsync(tryBody, null, _currentTestCaseIndex); | 771 return _guardAsync(tryBody, null, currentTestCase); |
| 777 } | 772 } |
| 778 | 773 |
| 779 _guardAsync(Function tryBody, Function finallyBody, int testNum) { | 774 _guardAsync(Function tryBody, Function finallyBody, TestCase testCase) { |
| 780 assert(testNum >= 0); | 775 assert(testCase != null); |
| 781 try { | 776 try { |
| 782 return tryBody(); | 777 return tryBody(); |
| 783 } catch (e, trace) { | 778 } catch (e, trace) { |
| 784 _registerException(testNum, e, trace); | 779 _registerException(testCase, e, trace); |
| 785 } finally { | 780 } finally { |
| 786 if (finallyBody != null) finallyBody(); | 781 if (finallyBody != null) finallyBody(); |
| 787 } | 782 } |
| 788 } | 783 } |
| 789 | 784 |
| 790 /** | 785 /** |
| 791 * Registers that an exception was caught for the current test. | 786 * Registers that an exception was caught for the current test. |
| 792 */ | 787 */ |
| 793 void registerException(e, [trace]) { | 788 void registerException(e, [trace]) { |
| 794 _registerException(_currentTestCaseIndex, e, trace); | 789 _registerException(currentTestCase, e, trace); |
| 795 } | 790 } |
| 796 | 791 |
| 797 /** | 792 /** |
| 798 * Registers that an exception was caught for the current test. | 793 * Registers that an exception was caught for the current test. |
| 799 */ | 794 */ |
| 800 void _registerException(testNum, e, [trace]) { | 795 void _registerException(TestCase testCase, e, [trace]) { |
| 801 trace = trace == null ? '' : trace.toString(); | 796 trace = trace == null ? '' : trace.toString(); |
| 802 String message = (e is TestFailure) ? e.message : 'Caught $e'; | 797 String message = (e is TestFailure) ? e.message : 'Caught $e'; |
| 803 if (testCases[testNum].result == null) { | 798 if (testCase.result == null) { |
| 804 testCases[testNum].fail(message, trace); | 799 testCase.fail(message, trace); |
| 805 } else { | 800 } else { |
| 806 testCases[testNum].error(message, trace); | 801 testCase.error(message, trace); |
| 807 } | 802 } |
| 808 } | 803 } |
| 809 | 804 |
| 810 /** | 805 /** |
| 811 * Runs a batch of tests, yielding whenever an asynchronous test starts | 806 * Runs a batch of tests, yielding whenever an asynchronous test starts |
| 812 * running. Tests will resume executing when such asynchronous test calls | 807 * running. Tests will resume executing when such asynchronous test calls |
| 813 * [done] or if it fails with an exception. | 808 * [done] or if it fails with an exception. |
| 814 */ | 809 */ |
| 815 void _nextBatch() { | 810 void _nextBatch() { |
| 816 while (true) { | 811 while (true) { |
| 817 if (_currentTestCaseIndex >= testCases.length) { | 812 if (_currentTestCaseIndex >= testCases.length) { |
| 818 _completeTests(); | 813 _completeTests(); |
| 819 break; | 814 break; |
| 820 } | 815 } |
| 821 final testCase = testCases[_currentTestCaseIndex]; | 816 final testCase = testCases[_currentTestCaseIndex]; |
| 822 var f = _guardAsync(testCase._run, null, _currentTestCaseIndex); | 817 var f = _guardAsync(testCase._run, null, testCase); |
| 823 if (f != null) { | 818 if (f != null) { |
| 824 f.whenComplete(() { | 819 f.whenComplete(() { |
| 825 _nextTestCase(); // Schedule the next test. | 820 _nextTestCase(); // Schedule the next test. |
| 826 }); | 821 }); |
| 827 break; | 822 break; |
| 828 } | 823 } |
| 829 _currentTestCaseIndex++; | 824 _currentTestCaseIndex++; |
| 830 } | 825 } |
| 831 } | 826 } |
| 832 | 827 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 911 } | 906 } |
| 912 | 907 |
| 913 /** Enable a test by ID. */ | 908 /** Enable a test by ID. */ |
| 914 void enableTest(int testId) => _setTestEnabledState(testId, true); | 909 void enableTest(int testId) => _setTestEnabledState(testId, true); |
| 915 | 910 |
| 916 /** Disable a test by ID. */ | 911 /** Disable a test by ID. */ |
| 917 void disableTest(int testId) => _setTestEnabledState(testId, false); | 912 void disableTest(int testId) => _setTestEnabledState(testId, false); |
| 918 | 913 |
| 919 /** Signature for a test function. */ | 914 /** Signature for a test function. */ |
| 920 typedef dynamic TestFunction(); | 915 typedef dynamic TestFunction(); |
| OLD | NEW |