Łukasz Dębowski
Łukasz Dębowski

Reputation: 51

Flutter integration tests - multiple tests

So I recently wanted to add some integration testing to the my app, and followed the official guidelines from the flutter.dev on the integration testing. I managed to run a single test, so I wanted to add another one, and this is where the problems started.

I don't know how to add another test suite in the same run, so something like

TEST 1:

  1. click button
  2. check if counter incremented

TEST2:

  1. click the button again
  2. check if counter incremented again
void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('Integration test', () {
    testWidgets('test 1', (WidgetTester tester) async {
      app.main();
      await tester.pumpAndSettle();

      // doing stuff here works
    });
  });
}

This is what I have working right now. I expected that moving the app.main() call before the group and simply adding another testWidgets call will work (similar to unit testing) but it doesn't:

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();
  // app.main(); <<--- moving here...
  group('Integration test', () {
    // app.main(); <<--- ... or here didn't help
    testWidgets('test 1', (WidgetTester tester) async {
      // do stuff
    });
    testWidgets('test 2', (WidgetTester tester) async {
      // how to add this? And do stuff with the same app session
    });
  });
}

EDIT: For better clarity of what I'm trying to achieve. The following are some current flutter driver tests that I have. I just want to migrate to the new api of integration_test package, without losing the names "test 1", "test 2" etc

void main() {
  group("group name", () {
    FlutterDriver driver;
    setUpAll(() async {
      driver = await FlutterDriver.connect();
    });

    tearDownAll(() async {
      if (driver != null) {
        await driver.close();
      }
    });

    test('test 1', () async {
      // do stuff with the driver
    });
    test('test 2', () async {
      // do other stuff with the driver with the same seesion
    });
    test('test 3', () async {
      // etc
    });
  });
}

Upvotes: 5

Views: 4978

Answers (3)

Alexander Dischberg
Alexander Dischberg

Reputation: 2298

Here is how I run multiple test using integration_test, the SharedPreferences data seems to be preserved between test. (doesn't work with multiple group). I just recently migrated from using raw test driver to integration_test.

You have to start the app in setUp block, and simply write the test in different testWidgets.

Note: This will throw sqlite error since there is no way to make sure the app is close and reopen and this will open a new instance for each testWidget. Let me know if anyone know how to work around this issue.

import 'package:my_app/main.dart' as app;

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  setUpAll(() {
    // this will start the app for each subsequent test
    app.main();
  });
  
  group('Smoke Test', () {
    testWidgets('Integration 1', (WidgetTester tester) async {
      ...
    });

    testWidgets('Integration 2', (WidgetTester tester) async {
     ...
    });
  );
}

Upvotes: 1

Lee Mordell
Lee Mordell

Reputation: 651

After the first test, I've got subsequent test cases to run successfully by pumping the main app into the test, e.g.

import 'package:my_app/main.dart' as app;

testWidgets('Test 1', (WidgetTester tester) {
    app.main();
    await tester.pumpAndSettle();

    // Tests ...
});

testWidgets('Test 2', (WidgetTester tester) {
    await tester.pumpWidget(app.MyApp());
    await tester.pumpAndSettle();

    // Tests ...
});

Upvotes: 1

zerotje09
zerotje09

Reputation: 345

I assume your app.main() is booting the actual app. It is not possible to boot the app just once at the start of a group. You have to boot the app within the testWidgets().

It might be useful to create a restartApp() which can be triggered at the start of every testWidgets(). This way you'll be able to start your new test fresh from the start.

You should add an UniqueKey() to the app root widget. This UniqueKey() needs to be re-generated after the restartApp(). Your app will recognise the key being changed so it will perform a reload.

testWidgets('test 1', (WidgetTester tester) async {
    restartApp();
    clickButton();
    // expect count incremented
  });

testWidgets('test 2', (WidgetTester tester) async {
    restartApp();
    clickButton();
    // expect count incremented
    clickButton();
    // expect count incremented again
  });

Upvotes: 3

Related Questions