Running automated

Flutter

integration tests 

Majid Hajian

mhadaily

mhadaily

Productive

 Beautiful

Fast

Open

mhadaily

mhadaily

Agenda

  • Firebase Test Lab
  • Summary
  • Integration Test

ME.dart

import 'package:flutter/material.dart';
MaterialApp(
   ThemeData(
        name: "Majid Hajian",
        location: "Oslo, Norway",
        description: '''
                Google Developer Expert
        	Passionate Software engineer, 
	        Community Leader, Author and international Speaker
         ''',
        main: "Flutter/Dart, PWA, Performance",
        homepage: "https://www.majidhajian.com",
        socials: {
          twitter: "https://www.twitter.com/mhadaily",
          github: "https://www.github.com/mhadaily"
        },
        author: {
          Pluralsight: "www.pluralsight.com/authors/majid-hajian",
          Apress: "Progressive Web App with Angular, Book",
          PacktPub: "PWA development",
          Udemy: "PWA development",
        }
        founder: "Softiware As (www.Softiware.com)"
        devDependencies: {
          tea: "Ginger", 
          mac: "10.14+",
        },
        community: {
          MobileEraConference: "Orginizer",
          FlutterVikings: "Orginizer", 
          FlutterDartOslo: "Orginizer",
          GDGOslo: "Co-Orginizer",
          DevFestNorway: "Orginizer",
          ...more
        }));

mhadaily

Find me on the internet by

mhadaily

Integration Test

  •  Real device or OS emulators
  •  App functions correctly as a whole
  •  Test complete app or part of it

  •  Measure performance
  •  Slowest execution
  •  Highest maintenance cost

mhadaily

Packages

flutter_driver

Integration_test

mhadaily

Packages

flutter_driver

Integration_test

mhadaily

integration_test

 Simpler to write test

 Similar to widget tests

 Compatible format with flutter drive and native Android instrumentation testing

 Android and iOS device testing

 Firebase Test Lab

mhadaily

testWidgets(
    "Loading -> tab login button -> see login screen",
    (WidgetTester tester) async {
      app.main();
      await tester.pump();

      expect(find.byType(SplashScreen), findsOneWidget);

      await tester.pumpAndSettle(const Duration(seconds: 3));

      final homeLoginButton = find.byKey(Key('homeLoginButton'));

      expect(homeLoginButton, findsOneWidget);

      await tester.tap(homeLoginButton);

      await tester.pumpAndSettle();

      expect(find.byType(LoginScreen), findsOneWidget);
    },
  );
testWidgets(
    "Loading -> tab login button -> enter correct username password -> see MenuScreen",
    (WidgetTester tester) async {
      app.main();
      await tester.pump();
      await tester.pumpAndSettle(const Duration(seconds: 3));
      final homeLoginButton = find.byKey(Key('homeLoginButton'));
      await tester.tap(homeLoginButton);
      await tester.pumpAndSettle();

      Finder emailField = find.byKey(Key('email'));
      expect(emailField, findsOneWidget);
      await tester.enterText(emailField, 'email');

      Finder passwordField = find.byKey(Key('password'));
      expect(passwordField, findsOneWidget);
      await tester.enterText(passwordField, 'password');

      await tester.tap(find.byKey(Key('signIn')));

      await tester.pumpAndSettle(Duration(seconds: 5));

      expect(find.byType(SnackBar), findsNothing);
      expect(find.byType(MenuScreen), findsOneWidget);
    },
  );

Automation

name:  Test, build and deploy
on: [push,pull_request]
jobs:
  drive_android:
    runs-on: macos-latest
    strategy:
      matrix:
        api-level: [21, 29]
        target: [default]
    needs: test
    steps:
      - uses: actions/checkout@v1
      - uses: subosito/flutter-action@v1
        with:
          flutter-version: '2.2.0'
          channel: 'stable'
      - name: Run Flutter Integration tests
        #GitHub Action for installing, configuring and running Android Emulators (work only Mac OS)
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: ${{ matrix.api-level }}
          target: ${{ matrix.target }}
		  # emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
          arch: x86_64
          profile: Nexus 6
          script: flutter drive --driver=test_driver/package_info_web_integration_test.dart --target=test_driver/package_info_web_integration.dart

1

package com.example.error_reporting_features_in_a_flutter_app;

import androidx.test.rule.ActivityTestRule;
import dev.flutter.plugins.integration_test.FlutterTestRunner;
import org.junit.Rule;
import org.junit.runner.RunWith;

// Make sure this is replaced with your app package name
// import MainActivity from our main app
import com.example.error_reporting_features_in_a_flutter_app.MainActivity;

@RunWith(FlutterTestRunner.class)
public class MainActivityTest {
  @Rule
  public ActivityTestRule<MainActivity> rule = 
  new ActivityTestRule<>(MainActivity.class, true, false);
}








pushd android
# # flutter build generates files in android/ for building the app
flutter build apk
./gradlew app:assembleAndroidTest
./gradlew app:assembleDebug -Ptarget=integration_test/app_test.dart
popd




















pushd android
# # flutter build generates files in android/ for building the app
flutter build apk
./gradlew app:assembleAndroidTest
./gradlew app:assembleDebug -Ptarget=integration_test/app_test.dart
popd

gcloud auth activate-service-account --key-file=wiredbraincoffee-a1386-4485fb96c69f.json

gcloud --quiet config set project wiredbraincoffee-a1386	

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 \
  --timeout 2m \
  # --results-bucket=<RESULTS_BUCKET> \
  # --results-dir=<RESULTS_DIRECTORY>




















mhadaily

Summary

mhadaily

mhadaily

We learned

  • Flutter Test Lab
  • Integration Test

www.pluralsight.com/courses/debugging-testing-publishing-flutter-app

Majid Hajian

mhadaily

mhadaily

Codes/Slides

slides.com/mhadaily