Few Tricks For Flutter Integration Test

Its been approx 6 months that I am working on the flutter integration testing. I came across many scenarios which seems blockers and took more than expected time to solve the issues. Thought of Sharing those cases with solutions to the community via this blog. If you are new to Flutter Integration Testing, Please go through the official doc as pre-requite — Integration Test.

Case 1 : Test Case Stucked on One Screen

Let us consider a case, in your test, You tapped on a button that navigates you to another screen. But after that, it does not perform any further actions. Your test stuck to the test screen and you have to kill that process manually. One reason that I come across was using pumpAndSettle() after tapping on the Ongoing Animation Screen.

await _tester.tap(find.byKey("key"));
await _tester.pumpAndSettle();

We have two methods in the flutter integration test package related to waiting for frames to complete i.e pump() and pumpAndSettle().

Pump() :

await _tester.pump(Duration(milliseconds: 100)): 

It means we are asking the test to wait for 100 msec. It implies that we must know how many frames we want to pump. otherwise, we might face semi-rendering of widgets and the test might fail. After a timeout, it will not wait for further rendering of the widget.

PumpAndSettle() :

await _tester.pumpAndSettle():

It runs pump() every 100 msec until all the frames are rendered. By default timeout, duration is 10 minutes.

But now consider a case, We have ongoing animation on our screen. And we are waiting for all frames to complete rendering using pumpAndSettle(). It means we are waiting infinite time on screen for the animation to complete. This causes the Test to stuck on a single screen.

Avoid using pumpAndSettle() on ongoing Animations.

Case 2: Clicking on a SubText present in RichText

Let's consider a case, In our app, we have one Richtext which contains clickable Text. Whole RichText is not clickable. In such a situation, the below code will not solve the purpose.

await _tester.tap(find.textContaining(text)); // This will not work when Complete RichText is not clicable

To solve this problem, we have to Scan RichText’s every TextSpan till the time we found desired Text, and then we have to click on That TextSpan. We can achieve it via -

_findTextAndTap this method will search for desired text and once it will get the text and tap on that,
it will return false to main method, indicating that we have clicked the desired subtext.
We have to stop visiter search after desired text

bool _findTextAndTap(InlineSpan visitor, String textToBeMatched) {
if (visitor is TextSpan && visitor.text == textToBeMatched) {
(visitor.recognizer as TapGestureRecognizer).onTap();
return false;
return true;

Future<void> tapOnSubText(String subText) async {
final richText = (await _tester.widget(find.byKey("keyOfRichText"))) as RichText;
richText.text.visitChildren((visitor) => _findTextAndTap(visitor, subText));

Case 3: Can see the Widget in Tree but Test doesn’t able to Find

We come across a situation where we can see the widget in WidgetTree but when we try to find that widget using testWidget() is not able to reach it. One reason could be, a developer created that widget private intentionally, or unintentionally. so that no other module can access it. There could be other reasons also. In such cases, check widget is present or not. we can use widgetPredicates to find the widget.

Another use case of widgetPrediacte is if you want to fetch a finder with multiple checks. Eg. the Widget should be RickText type and should be desired text. All these can be accomplished.

final Finder widgetFinder = find.byWidgetPredicate((Widget widget) => widget is RichText && widget.text.toPlainText() == text);
return _tester.any(widgetFinder);

Stay tuned for More Tricks !!



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store