Overview
Flutter integration test is UI test flow of the app from the user perspective. We use integration_test
package that enables self-driving testing of Flutter code on devices and emulators. It adapts flutter_test
results into a format that is compatible with flutter drive
and native Android instrumentation testing. We are going to execute them locally and also in a more production-grade setup with Firebase Test Lab and Google Cloud.
Setting up the project
To start, add the bdd_widget_test
, integration_test
, build_runner
, and flutter_test
package to your pubspec.yaml
file :
dependencies: bdd_widget_test: ^1.2.1 integration_test: sdk: flutter dev_dependencies: build_runner: ^2.1.7 flutter_test: sdk: flutter
Create a build.yaml
file in your project :
targets: $default: sources: - integration_test/** - lib/** - $package$ builders: bdd_widget_test|featureBuilder: generate_for: - integration_test/**/*.feature options: stepFolderName: ../step
Driver Entrypoint
Create a folder called integration_test
at the root of the Flutter project and inside it a file called driver.dart
. This will run the integrationDriver
.
import 'package:integration_test/integration_test_driver.dart'; Future<void> main() => integrationDriver();
Then, create a folder named feature
and step
in integration_test
folder, and inside the step
folder create a file named the_app_is_running.dart
. For example :
Writing integration tests
Start create a feature file in the feature
folder. For example :
After that run this command to generate the test file in your terminal :
flutter pub run build_runner build --delete-conflicting-outputs --build-filter integration_test/**/*_test.dart
It will automate created the test file going to be called <name>_test.dart
. For example :
Using Flutter Driver to Run Tests
Just start up an emulator/simulator or even connect a real device through a USB and then run the following command :
flutter drive --driver=integration_test/<name_file_test_driver>.dart --target=integration_test/feature/<name_file_test.dart
For example :
flutter drive --driver=integration_test/common/driver.dart --target=integration_test/feature/demo_page/subcription_demo_page_test.dart
After running this command, you should see something similar on your emulator and also an output saying "All tests passed!" in the terminal.
Testing Android On Firebase Test Lab
Android Setup
Create an instrumentation test file in android/app/src/androidTest/java/com/example/myapp/ directory(replacing com, example, and myapp from app’s package name). You can get app’s package name from file MainActivity.kt
So, you have to make test file in android/app/src/androidTest/java/com/vl/safi/flutter_safi directory. You can name this test file MainActivityTest.java
// package com.example.myapp; package com.vl.safi.flutter_safi; import androidx.test.rule.ActivityTestRule; import dev.flutter.plugins.integration_test.FlutterTestRunner; import org.junit.Rule; import org.junit.runner.RunWith; @RunWith(FlutterTestRunner.class) public class MainActivityTest { @Rule public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class, true, false); }
Update your application's myapp/android/app/build.gradle
{ "consumer": { "name": "SafiMobile-Consumer" }, "interactions": [ { "description": "", "providerStates": [ { "name": "Get All Card By CustomerId" } ], "request": { "method": "GET", "path": "/cards/8f7f8a2c-14a3-422d-b1dd-6abc6325597d" }, "response": { "body": [ { "accountNo": "0190239038", "accountType": "MAIN_ACCOUNT", "cardId": "7ea584a2-08b7-44ec-b152-d56a75d96386", "cardType": "DP1", "customerId": "8f7f8a2c-14a3-422d-b1dd-6abc6325597d", "embossName": "Maria Santos Dela Crup", "orderingNumber": 1 } ], "headers": { "Content-Type": "application/json" }, "matchingRules": { "body": { "$": { "combine": "AND", "matchers": [ { "match": "type", "min": 1 } ] }, "$[*].accountNo": { "combine": "AND", "matchers": [ { "match": "type" } ] }, "$[*].accountType": { "combine": "AND", "matchers": [ { "match": "type" } ] }, "$[*].cardId": { "combine": "AND", "matchers": [ { "match": "regex", "regex": "^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$" } ] }, "$[*].cardType": { "combine": "AND", "matchers": [ { "match": "type" } ] }, "$[*].customerId": { "combine": "AND", "matchers": [ { "match": "type" } ] }, "$[*].embossName": { "combine": "AND", "matchers": [ { "match": "regex", "regex": "^[a-zA-Z ]*$" } ] }, "$[*].expiration": { "combine": "AND", "matchers": [ { "match": "type" } ] }, "$[*].internationalBlockingFlag": { "combine": "AND", "matchers": [ { "match": "type" } ] }, "$[*].maskingCardNo": { "combine": "AND", "matchers": [ { "match": "type" } ] }, "$[*].namePrinted": { "combine": "AND", "matchers": [ { "match": "type" } ] }, "$[*].orderingNumber": { "combine": "AND", "matchers": [ { "match": "integer" } ] }, "$[*].updatedAt": { "combine": "AND", "matchers": [ { "match": "type" } ] } } }, "status": 200 } } ], "metadata": { "pactRust": { "version": "0.1.2" }, "pactSpecification": { "version": "3.0.0" } }, "provider": { "name": "CardManager-Provider" } }
Firebase Test Lab
To using Firebase Test Lab, we can upload Android APK by manual upload or using command line. In this project we will use command line to upload Android APK for testing by Firebase Test Lab.
Create file android_integration.sh to build an instrumentation test for Android use gradle commands
pushd android # flutter build generates files in android/ for building the app flutter build apk ./gradlew app:assembleAndroidTest ./gradlew app:assembleDebug -Ptarget=integration_test/feature/safi_demo_test.dart popd
Google Cloud Setup
To send this apk to firebase automatically, we have to install Google Cloud SDK. Use this guide to install https://cloud.google.com/sdk/docs/install
Go to your Google Cloud console using google account used to access the Firebase Test Lab
Select your project and open Service Account from IAM & Admin menu
Find firebase-adminsdk from the list
In Action, go to manage key and generate the key in json format
Save the file in the roof of the application
Ensure the key is not publish
Go to IAM menu, and find firebase-adminsdk
If you don’t have editor role, you can edit and add role
Go to library from APIs & Services menu
Find Cloud Tool Results API and ensure the API is enable
Finally, update the android_integration.sh
... gcloud auth activate-service-account --key-file=simple-integration-d61f59baaea2.json gcloud --quiet config set project simple-integration gcloud firebase test android run --type instrumentation \ --app build/app/outputs/apk/debug/app-debug.apk \ --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk \
To authenticate the google cloud with service account we create, use key in –key-file=<KEY_FILE>
Set the project to firebase project ID. You can get Project ID in Project settings
Set firebase test with gcloud from common line for instrumentation test
Run
./android_integration.sh
You can see the result from firebase test lab
Reference:
Attachments:
Screen Shot 2022-04-25 at 09.03.24.png (image/png)
eFwKRkj1R5w-OlAKqX_RFW4pcj-Drm5LOqaW9q8rxsnIipz8T1R70MZnTUuV9DTI68BkdsXB9PhBN9iJsumZtlrSdmhoWllNlBttRcSYF5_0jPPPFbHT26G8kBQomFvGIs50wmK5 (image/png)
QCjdwD8EVM9Be73hIdg1PUENe5jeofFWb3DTCEc0s8N1srF6PhSJJIXJjR4g-8nv7bkwYpTw3mzFT17771JccsFqOVjLf9vNLeCG6vPowYQDn4C0N1rc_MJAXgQD7yjkNBf180cF (image/png)
QIlY5O_T4ahWJg2HBkzF9pULRmmbNfOOvDYAYChkVVY2CNm3xJGfdePippoC3LUTwHfXujDxFfT-2M-uSWJjzgi4CDwRayvo7EAGUbNG6my8Oca5eRWJieEicib3fDXYFam1zcQG (image/png)
uF-jxh5gb_RvOzajElPjg4cvHpQOxdtIvyBxe2BnZ81yr_9oCqJ85H9EyxhhSAxaH5XiCqiZN9vHjtAB9sMCA9N_jsRTPQMTiHnarDnGml2TsEcjw28uVfV3Vn4XeZgzCG5304nO (image/png)
Hl6k90AEmm2ojAS5C1hQFR64ErbBlldw1Es8P-2TEDuqtMNlFreV_hWNFSBy_g0CsxciE9jvJUs_2mxPDHoMEdxVF6mitqtQHbpF0JwhzU9B1UpaazaHK_n3j5PmcWaAazpUW2Ze (image/png)
Hl6k90AEmm2ojAS5C1hQFR64ErbBlldw1Es8P-2TEDuqtMNlFreV_hWNFSBy_g0CsxciE9jvJUs_2mxPDHoMEdxVF6mitqtQHbpF0JwhzU9B1UpaazaHK_n3j5PmcWaAazpUW2Ze (image/png)
ouDJt6NBPIlIG91YsrTIpRGaPH5Jdn1OMMkpS1m30LnpW5zbX6f_BIoCT8BRB38f18zHYwkrxm-8x1kFBWFgYYhCQgDdnK-hmWWHOSdTRTMKGi61v3i5rkBJNjd6pQKRhYj27XdI (image/png)
Y4ZMa7KbDu292aC_dp6y6liqyvg0T67TrXvLWj1x1uY5-adU66OmhwmdZQ4rY570UWghegXqyMf3uZuaN0xur51i7UbTTU1uq4YF2xVXhIDoBpeCWnVs6xZ4njLaumaXzTp3L34M (image/png)
0JgH6jcBdGmaXD_ZPXh9MBMl_ooXByy5cUOjcj1HiZfOnpPauarS0QnlpS8x3sB9qnCiQy1Q2UGYFC2ei-r9GdlXFEx-4IRjP1b_87tHMdjhjv8yJVuIl-S-Epqc3LvTTPsduzeW (image/png)
38rAs09_8dG9wNRETD0KyQDZzOX9YRUFnNjWhfC4bJ_GhlEzisIrz4l5-IbNQ7MjWCQBRLzdfnEEKyWIp1q5HEtj0N21Ip3A4iFggyvz3LbQkOgVA1-iLfJPaXEx_GZdW9uBVGe9 (image/png)
7IdscwyQs4JDugCjA2TF8Rx2GgtbN3l2S_KzLfFSRfWS6qBtwHjFPe5vOWe-03AUDfVyik5rr3X-13fJl8VXLxhYNCMOu7SeH--5fOPI9BaefnYUZdkdTClBp9UsrNzaoCqlam4m (image/png)
i1op_nx5S09b98OqQWWyC1-I2ZL99YEpEghDstslxbUAovt0SZWadslMM0Im739RJCEfhJKI2vTbCcFlAQ5Unv3fn_GUbBcimxqDNdS7XDuscvrHjFQkBrulPaAFNX5bsbWu5Ftm (image/png)
UNLT1IWtIAbMW5Uvm9EIXfMVK535uvYIs1dpZBEe8co8_hifrurFVE-ia1N6bFMzuqNO9KY5ycpc82fygndDtzHeuVPDlcds0sPZ-DvIU5iHgqrddg66cug8QOQtzNnlUmK6m2Kj (image/png)
JaauWQV1EPkuSPF9iUWRiMwU0zjtU5OSgySM-gfEVB7DLk7B81BEfJrVY0NynS5l0-DYPGkHxj6wHD24QKmL4CkrUF0OzHB_QQSct35EeXIzHJp_4Pw5PLQuDz6n4dCLGzgriOoV (image/png)
pYcNSl4_uKTKcfYo-8Pp3pYY5Earc4EB7g-aHqmDc74h97Y62wA6KUROT7gS6gkkGPUDHTASVAXxvoWkb5cabRdI4luLqaCri21vSHtL69Pw-pVjnDYJlNvVhrDAr0xtvUtKKr1T (image/png)
9Aht0Zl3wEtdM0twb-v5HWCcgz5KnwYtKu9y6ax4Q86qa9bPyxlDCtm3HW_jBl2EljdPLAqjckOcAuq2UMBh8KAfgq4BIICMCP07o2qXeuh1y9eQ6Ig7pALtAH8Kwqx7O6FO-B9D (image/png)
taAq9jrD0ms4O8QsRTTJz-29hBI-CNTMPNP-EYARVPwfQ6j6AF6C16UXaQdwjoKOwnMe2gapuwrCg_MilM-6oy-x_3jAvpM2W_51uPMnnE82C1aUkFYLq-azCjr2MmxXUfQpEqxH (image/png)
3e5OpJvbvOPq0j3XFs4mMyYBHmAje_czhFEyfa5xcj6vn8T651Cnt5Sfy-ZpP8FBOpVMxozjo2D1kqAvRhhpPvSeP3i3p2JpRAQ9DXhAXaHXiZlU2XMk2BjVQ0VhnjrUbCND8_n6 (image/png)
iwvtEuECe3aJg_NlItBksMAE51JOqHco7dcO1ORty7vU_XmydMwPlX0fcL2vgRX2e6yr4zA_P9F_FcovLDyIm8COF3OwmLT1e2cBrKxdiA2O2B3mmo6ZGusXsEh65l_XUQrDJXUz (image/png)
Screen Shot 2022-06-27 at 12.21.20.png (image/png)
Screen Shot 2022-06-27 at 12.21.55.png (image/png)
Screen Shot 2022-06-27 at 12.22.33.png (image/png)
Screen Shot 2022-06-27 at 12.36.47.png (image/png)