How to run integration tests on Flutter apps

Discover how to run integration tests on Flutter apps with setup steps, best practices, and mistakes to avoid.

Get Started free
How to run integration tests on Flutter apps
Home Guide How to run integration tests on Flutter apps

How to run integration tests on Flutter apps

Flutter, designed by Google, is a free and open-source framework for building visually appealing, natively compiled, and multi-platform applications from a single codebase.

Flutter has become quite popular due to its ability to create multi-platform apps. It enables users to build, deploy, and test web, mobile, desktop, and embedded applications from a single codebase.

Overview

Features of Flutter Framework:

  • Fast Development with Hot Reload
  • Multi-Platform Support
  • Modern and Reactive Framework
  • Easy-to-Learn Dart Language
  • Fluid and Intuitive UI
  • Extensive Widget Catalog
  • Consistent UI Across Platforms
  • Robust Performance and Stability

Steps To Perform Integration Testing In Flutter Apps

  • Create an app to test
  • Add the integration_test dependency
  • Create the test files
  • Write the integration test
  • Run the integration test

This article explores the Flutter framework and how to run integration tests on Flutter apps.

Introduction To Flutter

Flutter is an open-source mobile UI framework that can create Android and iOS apps (among other platforms) from a single codebase.

Generally, frameworks offer different features to develop mobile applications. For example, Android provides a framework based on Java and Kotlin to develop mobile apps, whereas iOS uses a framework based on Objective-C or Swift language.

As a result, Devs had to use two different languages and frameworks to develop applications for both OS. Naturally, a cross-platform framework like Flutter makes life simpler for them by saving resources, time, and effort.

Features of Flutter Framework

Here are some of the key features that set Flutter apart:

  • Facilitates fast development: Flutter accelerates coding with hot reload, allowing instant visual feedback.
  • Multi-Platform support: It enables building apps for Android, iOS, web, and desktop from a single codebase.
  • Provides a modern and reactive framework: Flutter’s widget-driven, reactive architecture simplifies dynamic UI creation.
  • Uses the easy to learn Dart programming language: The intuitive Dart language offers a smooth learning curve for developers.
  • Fluid and intuitive user interfaces: It delivers visually appealing and responsive interfaces for an optimal user experience.
  • Vast widget catalog: An extensive array of customizable widgets empowers rich, tailored app designs.
  • Runs the same UI for multiple platforms: Flutter ensures consistent user interfaces across all supported platforms.
  • Stable and Reliable: The framework is renowned for its robust performance and dependable stability.

Testing In Flutter Apps

Flutter supports three types of tests:

  • Unit Test: A unit test verifies the behavior of a method or class.
  • Widget Test: A widget test checks the behavior of Flutter widgets without having to run the app.
  • Integration Test: An integration test (also called end-to-end testing or GUI testing) runs the entire application.

Integration Testing In Flutter Apps

Unit tests and Widget tests can test individual classes, widgets, or functions. However, they don’t verify how individual components work together or monitor application performance on real devices. This is where integration tests come in.

Integration tests in Flutter are written using the integration test package, provided by the SDK. This is Flutter’s version of Selenium WebDriver (generic web), Protractor (Angular), Espresso (Android), or Earl Gray (iOS). The package internally uses flutter driver to drive the test on a device.

Tests written with the integration_test package can:

  1. Run directly on the target device, enabling tests on numerous Android or iOS devices.
  2. Run using flutter test integration_test.
  3. Use flutter_test APIs, which makes the creation of integration tests similar to creating widget tests.

Talk to an Expert

Migrating From Flutter Driver

When Flutter was introduced, integration tests were written using flutter_driver, which enabled testers to maintain programmatic control of a Flutter app. On running the futter drive command, it initiates 2 processes:

  • A “driver” process on the host machine (i.e. the developer’s laptop) that sends instructions to and receives data from the app.
  • The app is configured to identify connections coming from the driver process.

This allowed the developer to write tests in plain Dart that could interact with the app. However, it came with significant disadvantages:

  • The driver code couldn’t share any code with the app or unit tests. In fact, it couldn’t leverage any package: flutter dependencies.
  • It relied on strongly-typed APIs because it could not import Key, Widget, or MyCustomWidget. find.byType(‘EvnetsPage’) was often mistyped and misread

Integration_Test Package

The integration_test package was released to fix some of the issues mentioned above. Here, the code for tests runs in the same isolate as the app code itself. In other words, it can access the same memory. This essentially resolves the previous issues, and offers a few other benefits:

  • Same API as component tests.
  •  Can share code with the app.
  • Internal app state is totally visible to tests, and runApp is called inside the test.
  • Since tests are built into the app executable, they can now run on physical devices.

Steps To Perform Integration Testing In Flutter Apps

This example will demonstrate how to test a counter app. This demonstrates how to set up integration tests, how to verify if a specific text is being displayed by the app, how to tap specific widgets, and how to run integration tests.

In order to perform the Integration test, follow the below steps:

  1. Create an app to test.
  2. Add the integration_test dependency.
  3. Create the test files.
  4. Write the integration test.
  5. Run the integration test.

Step 1. Create an app to test

First, create an app for testing. This test will use a counter app produced by the flutter create command. This app will let a user tap on a button to increase one count.

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {

  const MyApp({Key? key}) : super(key: key);

  @override

  Widget build(BuildContext context) {

    return const MaterialApp(

      title: 'Counter App',

      home: MyHomePage(title: 'Counter App Home Page'),

    );

  }

}

class MyHomePage extends StatefulWidget {

  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override

  _MyHomePageState createState() => _MyHomePageState();

}

class _MyHomePageState extends State<MyHomePage> {

  int _counter = 0;

  void _incrementCounter() {

    setState(() {

      _counter++;

    });

  }

  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(

        title: Text(widget.title),

      ),

      body: Center(

        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,

          children: <Widget>[

            const Text(

              'You have pushed the button this many times:',

            ),

            Text(

              '$_counter',

              // Provide a Key to this specific Text widget. This allows

              // identifying the widget from inside the test suite,

              // and reading the text.

              key: const Key('counter'),

              style: Theme.of(context).textTheme.headline4,

            ),

          ],

        ),

      ),

      floatingActionButton: FloatingActionButton(

        // Provide a Key to this button. This allows finding this

        // specific button inside the test suite, and tapping it.

        key: const Key('increment'),

        onPressed: _incrementCounter,

        tooltip: 'Increment',

        child: const Icon(Icons.add),

      ),

    );

  }

}
Copied

Step 2. Add the integration_test dependency

Now, use the integration_test, flutter_driver, and flutter_test packages for writing integration tests.

Add these dependencies to the dev_dependencies section of the app’s pubspec.yaml file. The location of the package should be the Flutter SDK.

# pubspec.yaml

dev_dependencies:

  integration_test:

    sdk: flutter

  flutter_test:

    sdk: flutter
Copied

Step 3. Create the test files

Create a new directory, integration_test, with an empty app_test.dart file:

counter_app/

  lib/

    main.dart

  integration_test/

    app_test.dart
Copied

Step 4. Write the integration test

Now, write the integration test with the steps below:

  1. Initialize IntegrationTestWidgetsFlutterBinding, a singleton service that runs tests on a physical device.
  2. Interact and test widgets via the WidgetTester class.
  3. Test the necessary scenarios.
import 'package:flutter_test/flutter_test.dart';

import 'package:integration_test/integration_test.dart';

import 'package:introduction/main.dart' as app;

void main() {

  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('end-to-end test', () {

    testWidgets('tap on the floating action button, verify counter',

        (WidgetTester tester) async {

      app.main();

      await tester.pumpAndSettle();

      // Verifies that the counter starts at 0.

      expect(find.text('0'), findsOneWidget);

      // Finds the floating action button to tap on.

      final Finder fab = find.byTooltip('Increment');

      // Emulates a tap on the floating action button.

      await tester.tap(fab);

      // Triggers a frame.

      await tester.pumpAndSettle();

      // Verifies if the counter increments by 1.

      expect(find.text('1'), findsOneWidget);

    });

  });

}
Copied

Step 5. Run the integration test

The process of executing integration tests depends greatly on the platform used. If the platform so permits, You can test on mobile devices or web browsers.

Mobile

To test on a real iOS / Android device, first, connect the device and run the following command from the root of the project:

flutter test integration_test/app_test.dart
Copied

Or, specify the directory to run all integration tests:

flutter test integration_test
Copied

This command runs the app and integration tests on the target device.

Web

To test on a web browser (Chrome, in this example), Download ChromeDriver.

Next, create a new directory named test_driver containing a new file named integration_test.dart:

import 'package:integration_test/integration_test_driver.dart';

Future<void> main() => integrationDriver();
Copied

Launch WebDriver, for example:

chromedriver --port=4444
Copied

From the root of the project, run the following command:

flutter drive \

  --driver=test_driver/integration_test.dart \

  --target=integration_test/app_test.dart \

  -d web-server
Copied

Common Mistakes to avoid in Flutter Integration Testing

Here are some common mistakes to watch out for when writing Flutter integration tests:

  • Neglecting Asynchronous Operations: Failing to properly wait for animations, network responses, or state updates can lead to flaky tests that pass intermittently.
  • Hardcoding Widget Identifiers: Relying on fixed widget keys or text values makes tests brittle and susceptible to breakage during UI refactoring.
  • Overcomplicating Test Scenarios: Trying to cover too many features in a single test can obscure the root cause of failures and complicate debugging.
  • Insufficient Cleanup Between Tests: Not resetting the app state or cleaning up resources after each test can lead to interdependent tests and unpredictable results.
  • Poor Error Handling and Logging: Overlooking the use of logging or error capture mechanisms can make it harder to diagnose failures when they occur.
  • Ignoring Platform Differences: Failing to account for platform-specific behaviors may result in tests that pass in one environment but fail in another.
  • Not Integrating with CI/CD Pipelines: Skipping automation in your continuous integration setup can cause regressions to go unnoticed until much later in the development cycle.

BrowserStack App Automate Banner

Integration Tests In Flutter Apps With BrowserStack

In order to get the most out of Integration tests, tests must be run on multiple real device, platform, and OS combinations. You cannot comprehensively and accurately identify all possible bugs without testing apps in real user conditions, and that is where BrowserStack App Automate comes in.

BrowserStack’s real device cloud offers thousands of real mobile devices from major vendors and manufacturers for app testing (manual and automated). Each device is loaded with real operating systems – multiple versions of popular operating systems in use.

Test Flutter Apps on Real Devices for Free

Conclusion

With BrowserStack, QAs can access thousands of popular mobile device-OS combinations to test their app and script their automation cases without worrying about buying and updating devices and installing software. They just need to sign up for free, choose the required device-OS combination and start testing their app.

Tags
Appium Automation Testing Mobile App Testing