Flutter Integration Testing Made Easy: Insider Tips and Tricks
- Article
Article
Flutter Integration Testing Made Easy: Insider Tips and Tricks
In our previous blogs of this series, we were :
Introduced to Flutter, approaches to testing Flutter applications
Then we compared Appium and Flutter Integration tests on 9 key parameters that help choose the appropriate tool
We wrote our first Flutter integration test using the Flutter Integration Test package
We executed the test and generated the HTML report locally
We Integrated Firebase Test Lab for Android Devices
We Integrated Firebase Test Lab for IOS Devices
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 where 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 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. E.g. 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);
Case 4: Tests are not getting Executed on Firebase Test Lab, Always says No Tests
It took me a long time to discover the root cause. Once we upload the Test and Debug APK to the Firebase Test lab , it expects Test Runner should be present internally to test the apk. We generally use debug apk for testing purposes and we keep minifyEnabled false in general.
If You are also facing the same issue, check your android/app/build.gradle and verify that minifyEnabled is false for debug mode.
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
signingConfig signingConfigs.debug
minifyEnabled false
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Verify minifyEnabled tag is False in your gradle file for debug build type.
Other Related Articles
integrating technology engineering thought leadership
Integrating Technology, Engineering and Thought Leadership Our DNA Integrating Technology, Engineering and Thought Leadership Technology, Engineering and Thought leadership are the foundational pillars to derive
how to automate workflow based applications using workflow design pattern
How to Automate Workflow-Based Applications using Workflow Design Pattern? Blog How to Automate Workflow-Based Applications using Workflow Design Pattern? “The best designers will use many
Scaling Tests on Google Kubernetes Engine with Cloud Build
Scaling Tests on Google Kubernetes Engine with Cloud Build Blog Scaling Tests on Google Kubernetes Engine with Cloud Build As we looked at how to
Share This Article