Skip to content
Blog

End-to-End Testing in Flutter: From flutter drive to integration_test Across Platforms

The integration_test package is the modern path for end-to-end Flutter testing, built on flutter_driver. Learn how to write and run integration tests across desktop, Android, iOS, web, and Firebase Test Lab.

Published on • October 21, 2026

AI Assistant

Unit tests prove your logic; widget tests prove your rendering. Neither proves that a real user can complete a flow on a real device. That gap is what integration testing fills — and in Flutter the story has an interesting wrinkle: the modern integration_test package is not a replacement for flutter_driver so much as a rebuild on top of it, which is why both names still appear in your pubspec.yaml.

Source: Check app functionality with an integration test, The Flutter Team, docs.flutter.dev.

The relationship between the two

When you add the integration test dependency:

flutter pub add "dev:integration_test:{sdk: flutter}"

the resolution pulls in integration_test, and — notably — flutter_driver and fuchsia_remote_debug_protocol alongside it. That is the lineage made visible. flutter_driver was the original end-to-end mechanism: it drove a device over a VM service protocol, commanding taps and reads from outside the app. integration_test keeps that device-driving capability (via the flutter drive command) but lets you write tests using the same flutter_test API you already know from widget tests — testWidgets, find, expect — running inside the app’s own process.

The practical benefit is one mental model. The same finder and matcher style from widget tests carries over; you are not learning a second driver API.

Writing the test

An integration test lives in an integration_test/ directory and needs the binding initialized:

import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:my_app/main.dart';

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('end-to-end test', () {
    testWidgets('increments the counter', (tester) async {
      await tester.pumpWidget(const MyApp());

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

      final fab = find.byKey(const ValueKey('increment'));
      await tester.tap(fab);
      await tester.pumpAndSettle();

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

Two details matter for reliability. Give interactive widgets a Key so your finder is stable rather than depending on visible text or structure. And use pumpAndSettle() after actions that trigger animations or async work, so assertions run against a settled frame.

Platform support — the real story

This is where integration_test earns its place. The same test can run across a surprising range of targets:

  • Desktop — Windows, macOS, and Linux run integration tests directly.
  • Android — on a physical device or emulator via flutter drive.
  • iOS — on a device or simulator via flutter drive.
  • Web — in a browser, which is where many teams underestimate it.
  • Firebase Test Lab — for automated runs across a matrix of real devices, on both Android and iOS.

That breadth is the argument for investing here. A single end-to-end suite that exercises a checkout flow can run on your desktop for speed, on a web build for the browser path, and in Test Lab against a device matrix before release — all from the same test file.

Running them

Execution is via flutter drive (or flutter test for the in-process cases), pointing at your target device, emulator, browser, or Test Lab. The test package uses the flutter_test APIs to write tests in a style similar to widget tests, so the CI wiring is a straightforward extension of what you already run — the same flutter test invocation, plus device-targeted drive invocations for the e2e legs.

Key takeaways

integration_test is the modern end-to-end testing package for Flutter, built on flutter_driver — which is why adding it pulls the driver in transitively. You write tests with familiar flutter_test finders and matchers, initialize IntegrationTestWidgetsFlutterBinding, and key your interactive widgets for stable finders. The payoff is platform breadth: the same suite runs on desktop, Android, iOS, web, and Firebase Test Lab, making one investment cover every release surface.

Further reading