Andreas B.
Andreas B.

Reputation: 311

New integration_test package just shows "Test starting..." [Android]

I tried to migrate my old flutter driver tests to the new integration_test package. I copied nearly everything from the example project and executed the integration tests of the example project locally. That worked as expected, I was able to see the app UI. But my own app just shows "Test starting..." in a purple color after the splash screen was shown.

example_test.dart:

void main() {
  group('My-App', () {
    final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding;

    testWidgets('Tap on SkipAuthentication', (tester) async {
      app.main();

      await binding.traceAction(() async {
        await tester.pumpAndSettle();

        await Future.delayed(Duration(seconds: 5));

        final fab = find.byKey(ValueKey(WidgetKeys.authenticationScreenKeys.skipAuthenticationButton));
        await tester.tap(fab);

        await tester.pumpAndSettle();
      });
    });



integration_driver.dart:

Future<void> main() async {
  integrationDriver();
}

I figured out, that if I don't start the tester.pumpWidget() shows the Widget, that I pass to the method, but thats a WidgetTest and not an integration Test.

My guess is, that it's due to the fact that my main function is an async function. I also needed this workaround in my old flutter driver tests to wait for the first frame. But I couldn't figure out how to implement that with the new integration_test package.

Hope you can help me.

Upvotes: 21

Views: 4780

Answers (6)

David Chopin
David Chopin

Reputation: 3064

I had been working on integration tests one day. The next day, I had pulled down some changes to the integration tests that my coworker had made. Suddenly, I was stuck on "Test loading..." when running on a simulator. I had been running from an Android Studio run configuration rather than through the command line directly. In any case...

The fix for me was to uninstall it from my simulator and try running again 🙃

Upvotes: 0

vkopio
vkopio

Reputation: 1014

I had this issue also and the sleep / Future.delayed did not work. Some times the integration tests were run but mostly they were not.

What ultimately fixed the issue for me was to change the framePolicy of IntegrationTestWidgetsFlutterBinding to LiveTestWidgetsFlutterBindingFramePolicy.fullyLive. Here is a full example:

void main() {
  final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;

  testWidgets("failing test example", (WidgetTester tester) async {
    app.main();
    await tester.pumpAndSettle();

    // Start testing here...
  });
}

The solution was found from Google Codelabs.

Upvotes: 10

AJay
AJay

Reputation: 11

Using Nils answer as a hint, I think I know partially what the issue is. If you go to the app's main.dart, and find that main() returns a Future, you have to wait for the main to finish.

// main.dart
Future<void> main() async {
...
}

If you see something like the previous in your main.dart, it means your app needs to await its startup. You cannot merely call app.main() because that function returns a Future. Calling that will not boot up your app properly (it will, but asynchronously and your next line of code will execute without the initialization being complete).

So instead of this:

testWidgets('Tap on SkipAuthentication', (tester) async {
  app.main(); // doesn't wait for initializing
  // ... next line will be executed right away
});

You will have to do something like this:

testWidgets('Tap on SkipAuthentication', (tester) async {
  await app.main(); // waits for an async app to initialize
  // ... next line will wait for app setup
});

Upvotes: 1

Elisa
Elisa

Reputation: 51

I had to use a combination of commands from this thread to make my test work. At first, it was getting stuck on "Test starting..." for me as well, then it was getting stuck on the splash screen. In both cases, it could not move to the first page of the app, so I could not find any widget.

A few things I kind-of learned from all my tries:

  • apparently, using pumpAndSettle() with its Duration argument gives different results than sleep(Duration) plus pumpAndSettle() without duration. The first worked for me to "get" the app's first page, but not the latter
  • calling tester.pumpWidget(MyApp()) instead of app.main() is actually resulting in an error screen for me, I definitely need to use app.main()
  • the framePolicy setting is necessary in my case as well
  • I think that using ValueKey or Key inside find.byKey is the same: for me, both of them are working (giving them a string as argument)

In the end, the code that works for me is:

void main() {
  final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() 
    as IntegrationTestWidgetsFlutterBinding;
  binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
    
  testWidgets('Tap on SkipAuthentication', (tester) async {
    app.main();
    await tester.pumpAndSettle(Duration(seconds: 3));

    final fab = find.byKey(ValueKey(WidgetKeys.authenticationScreenKeys.skipAuthenticationButton));
    await tester.tap(fab);

    await tester.pumpAndSettle();
  });
}

Upvotes: 1

Nils Reichardt
Nils Reichardt

Reputation: 3589

I was struggling with this also for some hours and finally found the answer.

Your issue is that do not pump a widget with await tester.pumpWidget(MyApp())

Your test look like:

void main() {
    testWidgets('Tap on SkipAuthentication', (tester) async {
      app.main(); // <--- You call app.main() - This Flutter Driver style, but not integration test style

      await binding.traceAction(() async {
        await tester.pumpAndSettle();

        await Future.delayed(Duration(seconds: 5));

        final fab = find.byKey(ValueKey(WidgetKeys.authenticationScreenKeys.skipAuthenticationButton));
        await tester.tap(fab);

        await tester.pumpAndSettle();
      });
    });

You need to change your test like this:

void main() {
  testWidgets('Tap on SkipAuthentication', (tester) async {
    await tester.pumpWidget(MyApp()); // You need to call await tester.pumpWidget();
    await tester.pump(const Duration(seconds: 1));

    final fab = find.byKey(ValueKey(WidgetKeys.authenticationScreenKeys.skipAuthenticationButton));
    await tester.tap(fab);

    await tester.pump();
  });
}

Upvotes: 1

Zal&#225;n Meggyesi
Zal&#225;n Meggyesi

Reputation: 654

Huh. I started converting my flutter_driver tests over the holidays and ran into the same thing.

My fix was to add a fixed sleep after launching the test, which allowed it to initialize properly. So one test case looks like this:

    testWidgets("Main screen loads", (WidgetTester widgetTester) async {
      app.main();
      await sleep(Duration(seconds: 10));
      await widgetTester.pumpAndSettle();

      expect(find.text("What are you looking for?"), findsOneWidget);
    });

Upvotes: 1

Related Questions