Flutter integration tests - multiple tests

1,677

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
  });
Share:
1,677
Admin
Author by

Admin

Updated on December 17, 2022

Comments

  • Admin
    Admin over 1 year

    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
        });
      });
    }
    
  • Łukasz Dębowski
    Łukasz Dębowski almost 3 years
    You are correct, the app.main() boots the app, just like it does in the docs The restarting part is a nice idea, but does not really get me where I want to get :/ The thing is, imagine you have a complicated flow that you want to test. I would like to be able to divide this flow into multiple tests that I can name, e.g: 1. add item to cart 2. add second item to cart 3. remove first item from cart 4. submit the cart 5. expect that the cart was submitted with just the second item
  • Łukasz Dębowski
    Łukasz Dębowski almost 3 years
    So for that, I'd love to have 5 test cases described like these, so that when something fails, I will see exactly on which step it failed (instead of just having the entire flow fail)
  • zerotje09
    zerotje09 almost 3 years
    You are acceptance testing the app, so the whole flow needs to be in the same testWidgets(). You can insert multiple expects between the steps of your flow to make sure everything is going like expected. The expect will fail if the requirements aren't met with a clear error message.
  • Łukasz Dębowski
    Łukasz Dębowski almost 3 years
    I guess then it's not really possible to migrate from the flutter_driver to integration_test package, without losing all of the information that naming each tests gives me :( (I edited the question to explain what I want to achieve better)
  • zerotje09
    zerotje09 almost 3 years
    You can also divide the flow in multiple steps so every testWidgets() can test a small step of the whole flow. But you will have to repeat the steps necessary to get a scenario where you, for example, remove the first item.
  • zerotje09
    zerotje09 almost 3 years
    I noticed you changed the topic, please see the changes in my answer.