@@ -87,8 +87,8 @@ void defineReflectiveTests(Type type) {
8787 {
8888 var isSolo = _hasAnnotationInstance (classMirror, soloTest);
8989 var className = MirrorSystem .getName (classMirror.simpleName);
90- group = _Group (isSolo, _combineNames (_currentSuiteName, className),
91- classMirror.testLocation );
90+ group = _Group (
91+ isSolo, _combineNames (_currentSuiteName, className), classMirror);
9292 _currentGroups.add (group);
9393 }
9494
@@ -151,10 +151,22 @@ void _addTestsIfTopLevelSuite() {
151151 if (_currentSuiteLevel == 0 ) {
152152 void runTests ({required bool allGroups, required bool allTests}) {
153153 for (var group in _currentGroups) {
154+ var runningTestCount = 0 ;
154155 if (allGroups || group.isSolo) {
155156 for (var test in group.tests) {
156157 if (allTests || test.isSolo) {
157- test_package.test (test.name, test.function,
158+ test_package.test (test.name, () async {
159+ runningTestCount += 1 ;
160+ await group.ensureSetUpClass ();
161+ try {
162+ await test.function ();
163+ } finally {
164+ runningTestCount -= 1 ;
165+ if (runningTestCount == 0 ) {
166+ group.tearDownClass ();
167+ }
168+ }
169+ },
158170 timeout: test.timeout,
159171 skip: test.isSkipped,
160172 location: test.location);
@@ -210,14 +222,14 @@ bool _hasSkippedTestAnnotation(MethodMirror method) =>
210222 _hasAnnotationInstance (method, skippedTest);
211223
212224Future <Object ?> _invokeSymbolIfExists (
213- InstanceMirror instanceMirror , Symbol symbol) {
225+ ObjectMirror objectMirror , Symbol symbol) {
214226 Object ? invocationResult;
215227 InstanceMirror ? closure;
216228 try {
217- closure = instanceMirror .getField (symbol);
229+ closure = objectMirror .getField (symbol);
218230 // ignore: avoid_catching_errors
219231 } on NoSuchMethodError {
220- // ignore
232+ // ignore: empty_catches
221233 }
222234
223235 if (closure is ClosureMirror ) {
@@ -307,10 +319,13 @@ class _AssertFailingTest {
307319class _Group {
308320 final bool isSolo;
309321 final String name;
310- final test_package.TestLocation ? location;
311322 final List <_Test > tests = < _Test > [];
312323
313- _Group (this .isSolo, this .name, this .location);
324+ /// For static group-wide operations eg `setUpClass` and `tearDownClass` .
325+ final ClassMirror _classMirror;
326+ Future <Object ?>? _setUpCompletion;
327+
328+ _Group (this .isSolo, this .name, this ._classMirror);
314329
315330 bool get hasSoloTest => tests.any ((test) => test.isSolo);
316331
@@ -327,6 +342,19 @@ class _Group {
327342 tests.add (_Test (isSolo, fullName, function, timeout? ._timeout,
328343 memberMirror.testLocation));
329344 }
345+
346+ /// Runs group-wide setup if it has not been started yet,
347+ /// ensuring it only runs once for a group. Set up runs and
348+ /// completes before any test of the group runs
349+ Future <Object ?> ensureSetUpClass () =>
350+ _setUpCompletion ?? = _invokeSymbolIfExists (_classMirror, #setUpClass);
351+
352+ /// Runs group-wide tear down iff [ensureSetUpClass] was called at least once.
353+ /// Must be called once and only called after all tests of the group have
354+ /// completed
355+ void tearDownClass () => _setUpCompletion != null
356+ ? _invokeSymbolIfExists (_classMirror, #tearDownClass)
357+ : null ;
330358}
331359
332360/// A marker annotation used to instruct dart2js to keep reflection information
0 commit comments