dartunit-testingtesting

dart_test: how to execute `setUp` if a loop before `test` is used based on the data assigned in `setUp`?


The problem is in this code:

void main() {
  late List<int> data;

  setUp(() async {
    data = [11, 22, 33];
  });
  
  int counter = 0;
  for (final d in data) { // error
    test('data', () {
      expect(d, data[counter++]);
    });
  }
}

error:

Local 'data' has not been initialized.

How can we specify that the setUp function should be called before the data is used?

I tried wrapping test in group - same error.


Solution

  • After two days of agony, I found an optimal solution that allows you to use collection sets and call setUp and tearDown exactly at test time.

    Look, here's a simple wrapper:

    @isTest
    Future<void> testWith(
      Object description,
      dynamic Function() body, {
      dynamic Function()? setUp,
      dynamic Function()? tearDown,
    }) async {
      test(description, () async {
        await setUp?.call();
        await body.call();
        await tearDown?.call();
      });
    }
    

    Add the desired parameters as needed. Also everything can be asynchronous and work fine.

    Now we can execute this code (slightly expanded to demonstrate the capabilities):

    Future<void> main() async {
      late List<int> data;
      Future<void> setUpAction() async {
        print('setUpAction');
        data = [11, 22, 33];
      }
    
      Future<void> tearDownAction() async {
        print('tearDownAction');
        data = [];
      }
    
      await testWith(
        'Test_1 data',
        setUp: setUpAction,
        tearDown: tearDownAction,
        () {
          int counter = 0;
          for (final d in data) {
            print('test_1: $d');
            expect(d, data[counter++]);
          }
        },
      );
    
      await testWith(
        'Test_2 data',
        setUp: setUpAction,
        tearDown: tearDownAction,
        () {
          int counter = 0;
          for (final d in data.take(2)) {
            print('test_1: $d');
            expect(d, data[counter++]);
          }
        },
      );
    }
    

    The output to the console is as follows:

    setUpAction
    test_1: 11
    test_1: 22
    test_1: 33
    tearDownAction
    setUpAction
    test_1: 11
    test_1: 22
    tearDownAction
    

    If we use the setUpAction from this answer, we get two problems:


    Add the isTest annotation so idea can see your tests (if necessary, there is also an isTestGroup annotation) from package meta:

    Used to annotate a test framework function that runs a single test. Tools, such as IDEs, can show invocations of such function in a file structure view to help the user navigating in large test files. The first parameter of the function must be the description of the test.