Chromium Code Reviews| Index: pkg/unittest/lib/unittest.dart |
| =================================================================== |
| --- pkg/unittest/lib/unittest.dart (revision 18238) |
| +++ pkg/unittest/lib/unittest.dart (working copy) |
| @@ -329,6 +329,7 @@ |
| TestCase _testCase; |
| Function _shouldCallBack; |
| Function _isDone; |
| + String _id; |
| static const _sentinel = const _Sentinel(); |
| _init(Function callback, Function shouldCallBack, Function isDone, |
| @@ -352,14 +353,18 @@ |
| if (expectedCalls > 0) { |
| _testCase.callbackFunctionsOutstanding++; |
| } |
| + _id = ''; |
| } |
| _SpreadArgsHelper(callback, shouldCallBack, isDone) { |
| _init(callback, shouldCallBack, isDone); |
| } |
| - _SpreadArgsHelper.fixedCallCount(callback, expectedCalls) { |
| + _SpreadArgsHelper.fixedCallCount(callback, expectedCalls, id) { |
| _init(callback, _checkCallCount, _allCallsDone, expectedCalls); |
| + if (id != null) { |
| + _id = "$id "; |
| + } |
| } |
| _SpreadArgsHelper.variableCallCount(callback, isDone) { |
| @@ -372,7 +377,7 @@ |
| _after() { |
| if (_isDone()) { |
| - _handleCallbackFunctionComplete(_testNum); |
| + _handleCallbackFunctionComplete(_testNum, _id); |
| } |
| } |
| @@ -382,7 +387,8 @@ |
| // Always run except if the test is done. |
| if (_testCase.isComplete) { |
| _testCase.error( |
| - 'Callback called after already being marked as done ($_actualCalls).', |
| + 'Callback ${_id}called after already being marked ' |
| + 'as done ($_actualCalls).', |
| ''); |
| return false; |
| } else { |
| @@ -452,7 +458,7 @@ |
| /** Returns false if we exceded the number of expected calls. */ |
| bool _checkCallCount() { |
| if (_actualCalls > _expectedCalls) { |
| - _testCase.error('Callback called more times than expected ' |
| + _testCase.error('Callback ${_id}called more times than expected ' |
| '($_actualCalls > $_expectedCalls).', ''); |
| return false; |
| } |
| @@ -466,10 +472,13 @@ |
| * specified [count] times before it continues with the following test. Using |
| * [_expectAsync] will also ensure that errors that occur within [callback] are |
| * tracked and reported. [callback] should take between 0 and 4 positional |
| - * arguments (named arguments are not supported here). |
| + * arguments (named arguments are not supported here). [id] can be used |
| + * to provide more descriptive error messages if the callback is called more |
| + * often than expected. |
| */ |
| -Function _expectAsync(Function callback, {int count: 1}) { |
| - return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke; |
| +Function _expectAsync(Function callback, {int count: 1, String id}) { |
| + return new _SpreadArgsHelper. |
| + fixedCallCount(callback, count, id).invoke; |
| } |
| /** |
| @@ -478,23 +487,28 @@ |
| * specified [count] times before it continues with the following test. Using |
| * [expectAsync0] will also ensure that errors that occur within [callback] are |
| * tracked and reported. [callback] should take 0 positional arguments (named |
| - * arguments are not supported). |
| + * arguments are not supported). [id] can be used to provide more |
| + * descriptive error messages if the callback is called more often than |
| + * expected. |
| */ |
| // TODO(sigmund): deprecate this API when issue 2706 is fixed. |
| -Function expectAsync0(Function callback, {int count: 1}) { |
| - return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke0; |
| +Function expectAsync0(Function callback, {int count: 1, String id}) { |
| + return new _SpreadArgsHelper. |
| + fixedCallCount(callback, count, id).invoke0; |
| } |
| /** Like [expectAsync0] but [callback] should take 1 positional argument. */ |
| // TODO(sigmund): deprecate this API when issue 2706 is fixed. |
| -Function expectAsync1(Function callback, {int count: 1}) { |
| - return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke1; |
| +Function expectAsync1(Function callback, {int count: 1, String id}) { |
| + return new _SpreadArgsHelper. |
| + fixedCallCount(callback, count, id).invoke1; |
| } |
| /** Like [expectAsync0] but [callback] should take 2 positional arguments. */ |
| // TODO(sigmund): deprecate this API when issue 2706 is fixed. |
| -Function expectAsync2(Function callback, {int count: 1}) { |
| - return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke2; |
| +Function expectAsync2(Function callback, {int count: 1, String id}) { |
| + return new _SpreadArgsHelper. |
| + fixedCallCount(callback, count, id).invoke2; |
| } |
| /** |
| @@ -618,9 +632,10 @@ |
| /** |
| * Register a [setUp] function for a test [group]. This function will |
| * be called before each test in the group is run. Note that if groups |
| - * are nested only the most locally scoped [setUp] function will be run. |
| + * are nested only the most locally scoped [setUpTest] function will be run. |
| * [setUp] and [tearDown] should be called within the [group] before any |
| - * calls to [test]. |
| + * calls to [test]. The [setupTest] function can be asynchronous; in this |
| + * case it must return a [Future]. |
| */ |
| void setUp(Function setupTest) { |
| _testSetup = setupTest; |
| @@ -629,9 +644,10 @@ |
| /** |
| * Register a [tearDown] function for a test [group]. This function will |
| * be called after each test in the group is run. Note that if groups |
| - * are nested only the most locally scoped [tearDown] function will be run. |
| + * are nested only the most locally scoped [teardownTest] function will be run. |
| * [setUp] and [tearDown] should be called within the [group] before any |
| - * calls to [test]. |
| + * calls to [test]. The [teardownTest] function can be asynchronous; in this |
| + * case it must return a [Future]. |
| */ |
| void tearDown(Function teardownTest) { |
| _testTeardown = teardownTest; |
| @@ -641,7 +657,7 @@ |
| * Called when one of the callback functions is done with all expected |
| * calls. |
| */ |
| -void _handleCallbackFunctionComplete(testNum) { |
| +void _handleCallbackFunctionComplete(testNum, [id = '']) { |
| // TODO (gram): we defer this to give the nextBatch recursive |
| // stack a chance to unwind. This is a temporary hack but |
| // really a bunch of code here needs to be fixed. We have a |
| @@ -650,8 +666,13 @@ |
| // run synchronously. Bad things can then happen. |
| _defer(() { |
| if (_currentTest != testNum) { |
| - if (_tests[testNum].result == PASS) { |
| - _tests[testNum].error("Unexpected extra callbacks", ''); |
| + if (_tests[testNum].result == PASS && |
| + // This next test is a bit of a kludge, but saves us |
| + // adding some other way of identifying that this callback |
| + // is an asyn teardown (which would have already advanced |
|
justinfagnani
2013/02/08 01:36:48
asyn -> async
gram
2013/02/08 17:52:24
Done.
|
| + // _currentTest). |
| + id != '[Async tearDown completion handler] ') { |
| + _tests[testNum].error("${id}Unexpected extra callbacks", ''); |
|
justinfagnani
2013/02/08 01:36:48
add space between ${id} and Unexpected?
gram
2013/02/08 17:52:24
id already has a space if it is non-empty; this al
|
| } |
| return; // Extraneous callback. |
| } |
| @@ -663,11 +684,9 @@ |
| testCase.error( |
| 'More calls to _handleCallbackFunctionComplete() than expected.', |
| ''); |
| - } else if (testCase.callbackFunctionsOutstanding == 0) { |
| - if (!testCase.isComplete) { |
| - testCase.pass(); |
| - } |
| - _nextTestCase(); |
| + } else if (testCase.callbackFunctionsOutstanding == 0 && |
| + !testCase.isComplete) { |
| + testCase.pass(); |
| } |
| } |
| }); |
| @@ -675,8 +694,10 @@ |
| /** Advance to the next test case. */ |
|
justinfagnani
2013/02/08 01:36:48
Maybe explain that the test is deferred? When I sa
gram
2013/02/08 17:52:24
I don't believe _nextTestCase can be called before
justinfagnani
2013/02/08 18:36:57
I missed a return statement in test_case. Curious:
gram
2013/02/08 18:43:15
Without _defer, we can build up a very deep stack.
|
| void _nextTestCase() { |
| - _currentTest++; |
| - _testRunner(); |
| + _defer(() { |
| + _currentTest++; |
| + _testRunner(); |
| + }); |
| } |
| /** |
| @@ -695,9 +716,6 @@ |
| if (_currentTest < _tests.length) { |
| final testCase = _tests[_currentTest]; |
| testCase.error(msg, trace); |
| - if (testCase.callbackFunctionsOutstanding > 0) { |
| - _nextTestCase(); |
| - } |
| } else { |
| _uncaughtErrorMessage = "$msg: $trace"; |
| } |
| @@ -790,10 +808,6 @@ |
| } else { |
| _tests[testNum].error('Caught $e', trace); |
| } |
| - if (testNum == _currentTest && |
| - _tests[testNum].callbackFunctionsOutstanding > 0) { |
| - _nextTestCase(); |
| - } |
| } |
| /** |
| @@ -802,7 +816,9 @@ |
| * [done] or if it fails with an exception. |
| */ |
| _nextBatch() { |
| - while (_currentTest < _tests.length) { |
| + if (_currentTest >= _tests.length) { |
| + _completeTests(); |
| + } else { |
| final testCase = _tests[_currentTest]; |
| guardAsync(() { |
| testCase.run(); |
| @@ -810,13 +826,7 @@ |
| testCase.pass(); |
| } |
| }, null, _currentTest); |
| - |
| - if (!testCase.isComplete && |
| - testCase.callbackFunctionsOutstanding > 0) return; |
| - _currentTest++; |
| } |
| - |
| - _completeTests(); |
| } |
| /** Publish results on the page and notify controller. */ |