@@ -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
@@ -154,12 +154,16 @@ void _addTestsIfTopLevelSuite() {
154154 if (allGroups || group.isSolo) {
155155 for (var test in group.tests) {
156156 if (allTests || test.isSolo) {
157- test_package.test (test.name, test.function,
157+ test_package.test (test.name, () async {
158+ await group.ensureSetUpClass ();
159+ test.function ();
160+ },
158161 timeout: test.timeout,
159162 skip: test.isSkipped,
160163 location: test.location);
161164 }
162165 }
166+ test_package.tearDownAll (() => group.tearDownClass ());
163167 }
164168 }
165169 }
@@ -217,7 +221,7 @@ Future<Object?> _invokeSymbolIfExists(
217221 closure = instanceMirror.getField (symbol);
218222 // ignore: avoid_catching_errors
219223 } on NoSuchMethodError {
220- // ignore
224+ // ignore: empty_catches
221225 }
222226
223227 if (closure is ClosureMirror ) {
@@ -307,10 +311,14 @@ class _AssertFailingTest {
307311class _Group {
308312 final bool isSolo;
309313 final String name;
310- final test_package.TestLocation ? location;
311314 final List <_Test > tests = < _Test > [];
312315
313- _Group (this .isSolo, this .name, this .location);
316+ /// Shared across group-wide operations eg `setUpClass` and `tearDownClass` .
317+ final InstanceMirror _instance;
318+ Future <Object ?>? _setUpCompletion;
319+
320+ _Group (this .isSolo, this .name, ClassMirror classMirror)
321+ : _instance = classMirror.newInstance (const Symbol ('' ), []);
314322
315323 bool get hasSoloTest => tests.any ((test) => test.isSolo);
316324
@@ -327,6 +335,16 @@ class _Group {
327335 tests.add (_Test (isSolo, fullName, function, timeout? ._timeout,
328336 memberMirror.testLocation));
329337 }
338+
339+ /// Runs group-wide setup if it has not been started yet,
340+ /// ensuring it only runs once for a group. Set up runs and
341+ /// completes before any test of the group runs
342+ Future <Object ?> ensureSetUpClass () =>
343+ _setUpCompletion ?? = _invokeSymbolIfExists (_instance, #setUpClass);
344+
345+ /// Runs group-wide tear down after all tests of the group have
346+ /// run
347+ void tearDownClass () => _invokeSymbolIfExists (_instance, #tearDownClass);
330348}
331349
332350/// A marker annotation used to instruct dart2js to keep reflection information
0 commit comments