Flutter Android
Unit tests and flutter widget tests validate individual classes, functions, or widgets. You will not be able to validate how individual pieces work together in whole or capture the performance of an app running on real devices. To perform these tasks you could use Flutters' integration test solution.
Follow this guide to run integration tests for your Flutter app on Android.
What You'll Need
- A Sauce Labs account (Log in or sign up for a free trial license)
- Your Sauce Labs Username and Access Key
- Flutter mobile app. If you don't have one, you could use our Flutter Demo App:
Prepare Your Flutter Application For Integration Testing
-
Open your Flutter project in your favorite IDE.
-
In your Flutter app's
pubspec.yaml, add the following dependencies:dev_dependencies:integration_test:sdk: flutterflutter_test:sdk: flutter -
Create an instrumentation test file in your application’s
android/app/src/androidTest/java/com/example/myappdirectory. Replacecom, example,andmyAppwith the values from your app’s package name.Then, name this test file as
MainActivityTest.javaor another name of your choice.package com.example.myApp;import androidx.test.rule.ActivityTestRule;import dev.flutter.plugins.integration_test.FlutterTestRunner;import org.junit.Rule;import org.junit.runner.RunWith;import com.example.myApp.MainActivity;@RunWith(FlutterTestRunner.class)public class MainActivityTest {@Rulepublic ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class, true, false);} -
Update your application’s
myapp/android/app/build.gradlefile to ensure it uses androidx’s version ofAndroidJUnitRunnerand includes androidx libraries as a dependency.android {...defaultConfig {...testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}}dependencies {testImplementation 'junit:junit:4.12'androidTestImplementation 'androidx.test:runner:1.2.0'androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'} -
Create a directory called
integration_testin the root of your Flutter project. -
Create a file called
flutter_integration_test.dartin theintegration_testdirectory. -
Update your testing dart file
flutter_integration_test.dartto include the tearDownAll, The purpose for this is to make sure we close the connection to the device after the tests have completed.import 'package:flutter/material.dart';import 'package:flutter_test/flutter_test.dart';import 'package:integration_test/integration_test.dart'; // Ensure you have this import// Add as app because we want to make sure the app loaded correctly on the device by calling the main function in the main dart file.import 'package:my_demo/main.dart' as app;void main() {// Ensure IntegrationTestWidgetsFlutterBinding is initializedfinal binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding;group('E2E Test With Flutter', (){tearDownAll(() async {// Signal that the test is completebinding.reportData = <String, dynamic>{'completed': true,};});testWidgets("First testing scenario increment 5 decrement 3",(tester) async {app.main();await tester.pumpAndSettle(); // wait for app to be ready....});});} -
Use the following
Gradlecommands to build an instrumentation test.apkfile(test suite) using theMainActivityTest.javacreated in theandroidTestdirectory as mentioned in step 3.Terminal Command# Go to the android folder which contains the "gradlew" script used for building Android apps from the terminalpushd android# Build an Android test APK (uses the MainActivityTest.java file created in step 1)./gradlew app:assembleAndroidTest# Build a debug APK by passing the integration test file./gradlew app:assembleDebug -Ptarget="..../integration_test/flutter_integration_test.dart"# Go back to the root of the projectpopd -
Configure
saucectlto run the test.- Create a folder
saucectlin your project root directory. - Inside this folder create a
flutter_integration_test_android.yamlwith the following content:
apiVersion: v1alphakind: espressosauce:concurrency: 1espresso:app: ...../flutter/my-demo-app-flutter/build/app/outputs/flutter-apk/app-debug.apktestApp: ....../flutter/my-demo-app-flutter/build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apksuites:- name: "Sauce Labs Espresso with flutter integration tests"testOptions:class:- com.example.my_demo_app_flutter.MainActivityTestdevices:- name: "Google Pixel.*"artifacts:download:when: alwaysmatch:- junit.xmldirectory: ./- Run the following commands to start the test on Sauce Labs
Terminal Commandsaucectl configure -u USERNAME -a ACCESS_KEYsaucectl run -c sauceconnect/flutter_integration_test.yaml- Check the status of you test on
app.saucelabs.com
saucectl run command output12:24:52 INF Running Espresso in Sauce Labs(.#.#..#########################////////*******/######.##///////*****************###/,###////*********************#######//***********************#######/************************#########********************###. ##(######################## ## ##,######(#* ##* (##/############* #####(########( #########( ###.#######, */ ############,########## %#### , ########**### .#######/ ## / ########### .###########//################# ########################(#( *#( #######. (#########, /######## ########*######## ########_____ _ _ _____ ______ _____ _ ____ _ _ _____/ ____| /\ | | | |/ ____| ____| / ____| | / __ \| | | | __ \| (___ / \ | | | | | | |__ | | | | | | | | | | | | | |\___ \ / /\ \| | | | | | __| | | | | | | | | | | | | | |____) / ____ \ |__| | |____| |____ | |____| |___| |__| | |__| | |__| ||_____/_/ \_\____/ \_____|______| \_____|______\____/ \____/|_____/12:24:52 INF Checking if ...../my-demo-app-flutter/build/app/outputs/flutter-apk/app-debug.apk has already been uploaded previously12:24:52 INF Checksum: 1df0b6684973536fef4ae653d89661d6c48d6f699091511515b69735d6a80fbd12:27:26 INF Application uploaded. durationMs=153173 storageId=6849a64a-3c51-4423-87f2-b3660c972a3612:27:26 INF Checking if ...../build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk has already been uploaded previously12:27:26 INF Checksum: b5b15cb741b78fe7a5df171406c17ec9ea8fd6ac52623abf7a8df519270e281d12:27:26 INF Skipping upload, using storage:635a7a46-c1fc-4c43-9a05-60e09a2163b812:27:26 INF Launching workers. concurrency=112:27:26 INF Starting suite. region=us-west-1 suite="Sauce Labs Espresso with flutter integration tests"12:27:27 INF Suite started. deviceId= deviceName="Google Pixel.*" platform=Android platformVersion= private=false suite="Sauce Labs Espresso with flutter integration tests" url=https://app.saucelabs.com/tests/4b52d0880d5d41579d669a66fdca2da012:27:36 INF Suites in progress: 112:27:46 INF Suites in progress: 112:27:56 INF Suites in progress: 112:28:06 INF Suites in progress: 112:28:16 INF Suites in progress: 112:28:26 INF Suites in progress: 112:28:27 INF Suite finished. passed=true suite="Sauce Labs Espresso with flutter integration tests" url=https://app.saucelabs.com/tests/4b52d0880d5d41579d669a66fdca2da0Results:Name Duration Status Platform Device Attempts───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────✔ Sauce Labs Espresso with flutter integration tests 1m0s passed Android Google Pixel.* 1───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────✔ All tests have passed 1m1sBuild Link: https://app.saucelabs.com/builds/rdc/159d98f0223246e59dd172bad78573cc - Create a folder
Example Implementation
For a practical example of how to set up and run integration tests for Flutter apps, you can refer to the Sauce Labs Flutter demo application repository. The steps outlined in this guide have already been implemented in that repository. You can follow along with the demo app to see how everything is configured and run your tests accordingly.