Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(920)

Unified Diff: pkg/unittest/lib/unittest.dart

Issue 12213079: setUp/tearDown functions can now be asynchronous. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/unittest/lib/unittest.dart
===================================================================
--- pkg/unittest/lib/unittest.dart (revision 18267)
+++ 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 a wrapped async teardown (which would have already advanced
+ // _currentTest).
+ id != '[Async tearDown completion handler] ') {
Siggi Cherem (dart-lang) 2013/02/11 23:14:18 I'm still curious about why we need this check (se
gram 2013/02/11 23:50:24 Actually I think the expectAsync was spurious, so
+ _tests[testNum].error("${id}Unexpected extra callbacks", '');
}
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. */
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,21 +816,28 @@
* [done] or if it fails with an exception.
*/
_nextBatch() {
- while (_currentTest < _tests.length) {
+ while (true) {
+ if (_currentTest >= _tests.length) {
+ _completeTests();
+ break;
Siggi Cherem (dart-lang) 2013/02/11 23:14:18 nit: now that the tight loop is back, I have a sli
gram 2013/02/11 23:50:24 That won't work, as there is an async loop break t
+ }
final testCase = _tests[_currentTest];
+ var f;
guardAsync(() {
- testCase.run();
- if (!testCase.isComplete && testCase.callbackFunctionsOutstanding == 0) {
- testCase.pass();
- }
+ f = testCase.run();
}, null, _currentTest);
Siggi Cherem (dart-lang) 2013/02/11 23:14:18 is this equivalent to: var f = guardAsync(testCase
gram 2013/02/11 23:50:24 Yes! :-)
-
- if (!testCase.isComplete &&
- testCase.callbackFunctionsOutstanding > 0) return;
+ if (f != null) {
+ f.then((_){})
+ .catchError((e) {
+ testCase.error(e.toString(), e.stackTrace);
+ })
+ .whenComplete(() {
+ _nextTestCase(); // Schedule the next test.
+ });
+ break;
+ }
_currentTest++;
}
-
- _completeTests();
}
/** Publish results on the page and notify controller. */

Powered by Google App Engine
This is Rietveld 408576698