Chromium Code Reviews| Index: pkg/unittest/lib/unittest.dart |
| =================================================================== |
| --- pkg/unittest/lib/unittest.dart (revision 21778) |
| +++ pkg/unittest/lib/unittest.dart (working copy) |
| @@ -219,12 +219,16 @@ |
| /** Tests executed in this suite. */ |
| final List<TestCase> testCases = new UnmodifiableListView<TestCase>(_testCases); |
| -/** Setup function called before each test in a group */ |
| -Function _testSetup; |
| +/** Setup function called before each test in a group. */ |
| +Function _testSetup = null; |
| -/** Teardown function called after each test in a group */ |
| -Function _testTeardown; |
| +/** Teardown function called after each test in a group. */ |
| +Function _testTeardown = null; |
| +/** Setup and teardown functions of parent group, for chaining. */ |
| +Function _parentSetup = null; |
| +Function _parentTeardown = null; |
| + |
| int _currentTestCaseIndex = 0; |
| /** [TestCase] currently being executed. */ |
| @@ -607,13 +611,18 @@ |
| } |
| // Groups can be nested, so we need to preserve the current |
| - // settings for test setup/teardown. |
| - Function parentSetup = _testSetup; |
| - Function parentTeardown = _testTeardown; |
| + // settings for test setup/teardown. We use a local copy here so we |
| + // can nest multiple levels; we also have the global parent variables |
| + // which are used for chaining. |
| + Function _oldSetup = _testSetup; |
| + Function _oldTeardown = _testTeardown; |
| + Function _oldParentSetup = _parentSetup; |
| + Function _oldParentTeardown = _parentTeardown; |
| + _parentSetup = _testSetup; |
| + _parentTeardown = _testTeardown; |
| + |
| try { |
| - _testSetup = null; |
| - _testTeardown = null; |
| body(); |
| } catch (e, trace) { |
| var stack = (trace == null) ? '' : ': ${trace.toString()}'; |
| @@ -621,21 +630,30 @@ |
| } finally { |
| // Now that the group is over, restore the previous one. |
| _currentGroup = parentGroup; |
| - _testSetup = parentSetup; |
| - _testTeardown = parentTeardown; |
| + _testSetup = _oldSetup; |
| + _testTeardown = _oldTeardown; |
| + _parentSetup = _oldParentSetup; |
| + _parentTeardown = _oldParentTeardown; |
|
Siggi Cherem (dart-lang)
2013/04/19 23:55:05
now that we have 5 of these, it might be worth cre
|
| } |
| } |
| /** |
| * 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 [setUpTest] function will be run. |
| + * be called before each test in the group is run. |
| * [setUp] and [tearDown] should be called within the [group] before any |
| * calls to [test]. The [setupTest] function can be asynchronous; in this |
| * case it must return a [Future]. |
| */ |
| void setUp(Function setupTest) { |
| - _testSetup = setupTest; |
| + var parent = _parentSetup; |
| + _testSetup = () { |
| + var f = parent == null ? null : parent(); |
| + if (f is Future) { |
| + return f.then((_) => setupTest()); |
| + } else { |
| + return setupTest(); |
| + } |
| + }; |
| } |
| /** |
| @@ -647,7 +665,19 @@ |
| * case it must return a [Future]. |
| */ |
| void tearDown(Function teardownTest) { |
| - _testTeardown = teardownTest; |
| + var parent = _parentTeardown; |
| + _testTeardown = () { |
| + var f = teardownTest(); |
| + if (parent == null) return f; |
| + if (f is Future) { |
| + // TODO(gram): as _parentTeardown is a global, do we need |
| + // to first take a local copy so the value is fixed at the |
| + // point that tearDown is called? |
| + return f.then((_) => parent()); |
| + } else { |
| + return parent(); |
| + } |
| + }; |
| } |
| /** Advance to the next test case. */ |