why can't the widget finder in my integration test find a widget after my test successfully signs into my flutter app?

1,429

Solution 1

It seems that the trick is that the AppBar's default "leading" widget or the default leading widget's default tooltip is not present when the integration test is run. When the app is run in debug-mode in the emulator it is there - it can be found with a debug-watch on MaterialLocalizations.of(context).openAppDrawerTooltip. That watch does not find the tooltip when I run debug on the test file - then again no watches seem to work in that case.

The fix is to manually add the "leading" widget into the AppBar like so:

appBar: AppBar(
              title: "my title",
              leading: Builder(
                builder: (BuildContext context) {
                  return IconButton(
                    icon: Icon(Icons.menu),
                    onPressed: () {
                      Scaffold.of(context).openDrawer();
                    },
                    tooltip: 'Open navigation menu',
                  );
                },
              ),
...

Now, on to the next problem - why does the next test in the group fail to find any widgets?

Solution 2

There are several possible reasons why the widget is not found in this particular case:

  1. It is not present on the screen(either completely or scrolled out of the screen)
  2. The tooltip is incorrect either here or in the actual code.
  3. The widget you try to find is not Tooltip widget.
  4. The pumping time is too low.
  5. Maybe some emulator specific stuff.

Now what are possible fixes.

  1. If the widget is on the screen and is visible to you doesn't meen that it is visible to the test driver - from my experience it is a pretty common situation. You can try to use tester.ensureVisible to make it visible for sure. Or actually scroll the content to make sure it is visible with either tester.fling, tester.scrollUntilVisible or tester.dragUntilVisible.

  2. Check you tooltip string. I would recommend you not to use findByTooltip in this way - you may not know the excat locale of the device and if there will be Localization enabled for the app - the finder will fail. If you are completely sure that there won't be a localization in the app - create a static string with a tooltip and use it both in the code and in tests - this way you will be sure the string is the same. With localizations - use InheritedWidget approach and retrieve strings from context via appLocalizations.of(context) both in the implementation and tests. But the actual proposition here is not to use findByTooltip at all. findByKey is much more reliable because it is independent from context locale and manual entering mistake - just use Keys as I suggested before - create static consts keys and use the same const both in your code and tests.

  3. Check if the message field of your Tooltip is filled and is the same you try to find.

  4. Pump a bit more - maybe it will help. Also try to use pump with long duration and then pumpAndSettle with default duration directly one after the other - sometimes it helps.

  5. Try to run tests on real device.

The general answer to your question is that finder finds widgets if everything is correctly coded and there is such a widget on the screen. But I understand why it is somehow problematic - I have written several thousands of lines of flutter integration tests and I have seen all kinds of human mistakes(mine includingly), weird driver/tester/finder behaviours and device/os/framewok specific cases.

Share:
1,429
lost baby
Author by

lost baby

Updated on December 27, 2022

Comments

  • lost baby
    lost baby over 1 year

    I am trying to write some integration tests that start off with a login attempt then proceeds to navigate the app a bit to a certain page. The attempt to sign in actually succeeds but after that my attempts to find any widgets fails so I cannot navigate further.

    After the sign-in the page the app automatically navigates away to the next page in the app correctly but then my test script cannot find any widgets on that page even though I can see them in the android emulator onscreen.

    My app_test.dat file looks like this:

     
    import ...
    
    void main() {
      IntegrationTestWidgetsFlutterBinding.ensureInitialized();
      
      group('sign in : ', () {
        testWidgets('try to SIGN IN and  open the menu ',
            (WidgetTester tester) async {
          app.main();
          await tester.pumpAndSettle(const Duration(milliseconds: 5000));
          await tester.pumpAndSettle();
    
          expect(find.text('SIGN IN', skipOffstage: false), findsWidgets);
    
          expect(find.byKey(Key('loginPagePasswordField')), findsOneWidget);
          expect(find.byKey(Key('loginPageEmailField')), findsOneWidget);
          print('found fields');
          await tester.enterText(
              find.byKey(Key('loginPageEmailField')), '[email protected]');
          await tester.enterText(
              find.byKey(Key('loginPagePasswordField')), 'myname123zxc');
          print('entered text');
          await tester.testTextInput.receiveAction(TextInputAction.done);
          await tester.pump();
          print('entered DONE');
     
          await tester.pumpAndSettle(const Duration(milliseconds: 5000));
          await tester.pumpAndSettle();
    
    
          // Now try to find the menu icon button
          var x = find.byTooltip('Open navigation menu'); 
          expect(x, findsOneWidget);  // this fails but is needed to navigate the app
          print('find tab1 ');
          // Now try to find the 'ASD' Tab 
          final tabFinder = find.text('ASD', skipOffstage: false);
          expect(tabFinder, findsWidgets); // this also fails
      
        });
     
      });
    }
    

    and my f doctor (I use fvm):

    [✓] Flutter (Channel stable, 2.8.0, on macOS 12.1 21C52 darwin-arm, locale en-CA)
    [✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
    [✓] Xcode - develop for iOS and macOS (Xcode 13.2)
    [✓] Chrome - develop for the web
    [✓] Android Studio (version 2020.3)
    [✓] VS Code (version 1.63.0)
    [✓] Connected device (2 available)
    
    • No issues found!
    
  • lost baby
    lost baby over 2 years
    Thanks Pavlo, The particular widget I was looking for in this code was the hamburger icon for the drawer but I've tried other visible widgets onscreen to with no success. I've tried various pump calls with long durations etc. So far no luck. I wonder if the tester or find objects have become disconnected from the app. Is there a way to force them to re-attach? After the login the app uses a MaterialPageRoute to go to the next page with the sought after widgets.
  • lost baby
    lost baby over 2 years
    Pavlo, your answer turned out to be very close so if I can give you the bounty I will, is there a way to still do so?
  • Pavlo Ostasha
    Pavlo Ostasha over 2 years
    @lostbaby nope, but don't bother, glad it helped.