How to Add Integration Tests Using Flutter Driver and the integration_test Package
To add integration tests in Flutter, enable the Flutter Driver extension in a dedicated entry point, write tests using the integration_test package's WidgetTester API, and execute them with the flutter drive command.
Adding integration tests to your Flutter app ensures complete user flows work correctly across devices. According to the flutter/skills repository—specifically the flutter-add-integration-test skill documented in SKILL.md—you combine the modern integration_test package with the optional Flutter Driver extension to create robust end-to-end tests. This workflow leverages WidgetTester for assertions while maintaining compatibility with external automation tools and MCP servers.
Project Setup and Dependencies
Start by declaring the required development dependencies in your pubspec.yaml. You need both integration_test and flutter_test from the Flutter SDK.
# pubspec.yaml
dev_dependencies:
integration_test:
sdk: flutter
flutter_test:
sdk: flutter
These packages provide the IntegrationTestWidgetsFlutterBinding and the WidgetTester API necessary for driving the app UI and making assertions.
Enable the Flutter Driver Extension
Create a separate entry point file—conventionally lib/main_test.dart—that enables the driver extension before running your app. This step is required only if you need to support legacy flutter_driver workflows or MCP-driven interactive exploration.
// lib/main_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_driver/driver_extension.dart';
import 'package:my_app/main.dart';
void main() {
// Allows MCP / flutter_driver to control the app remotely
enableFlutterDriverExtension();
runApp(const MyApp());
}
The enableFlutterDriverExtension() function registers a service extension that permits external tools to query the widget tree and inject input events.
Author Integration Tests with the integration_test Package
Place your test files in the integration_test/ directory. Each test must initialize the binding and use WidgetTester to interact with widgets.
// integration_test/app_test.dart
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('tap FAB and verify counter', (WidgetTester tester) async {
await tester.pumpWidget(const MyApp());
// Verify counter starts at 0
expect(find.text('0'), findsOneWidget);
// Tap the button with ValueKey('increment')
await tester.tap(find.byKey(const ValueKey('increment')));
// Wait for animations to complete
await tester.pumpAndSettle();
// Verify counter incremented to 1
expect(find.text('1'), findsOneWidget);
});
});
}
The IntegrationTestWidgetsFlutterBinding.ensureInitialized() call bootstraps the test harness, while pumpAndSettle() ensures all frames and animations complete before assertions run.
Create the Host Driver Script
The flutter drive command requires a host driver script located in test_driver/. This minimal script acts as a bridge between the command-line tool and your integration test file.
// test_driver/integration_test.dart
import 'package:integration_test/integration_test_driver.dart';
Future<void> main() => integrationDriver();
The integrationDriver() function handles the communication protocol, forwards test results, and optionally collects performance timelines if profiling is enabled.
Run Tests with flutter drive
Execute your tests using the flutter drive command, specifying both the driver script and the target test file.
flutter drive \
--driver=test_driver/integration_test.dart \
--target=integration_test/app_test.dart
For web testing, first start chromedriver on port 4444, then specify the device:
chromedriver --port=4444
flutter drive \
--driver=test_driver/integration_test.dart \
--target=integration_test/app_test.dart \
-d chrome
This command compiles the app, launches it on the target device, executes the test logic, and reports results to the console.
Interactive Exploration via MCP
Before writing static tests, you can explore the app interactively using an MCP server that leverages the Flutter Driver extension. With the app running via lib/main_test.dart, the MCP tools can launch_app, get_widget_tree, tap, enter_text, and scroll to discover stable ValueKey identifiers. This exploration phase helps you identify the exact widget keys and navigation patterns to harden in your integration_test/app_test.dart file.
Summary
- Add
integration_testandflutter_testtodev_dependenciesinpubspec.yaml - Enable the driver extension by calling
enableFlutterDriverExtension()inlib/main_test.dartwhen legacy or MCP support is needed - Author tests in
integration_test/app_test.dartusingIntegrationTestWidgetsFlutterBinding.ensureInitialized()and theWidgetTesterAPI - Provide a host driver script at
test_driver/integration_test.dartthat delegates tointegrationDriver() - Execute the full suite with
flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart
Frequently Asked Questions
What is the difference between the integration_test package and Flutter Driver?
The integration_test package provides the modern, widget-level testing API using WidgetTester and is the recommended approach for new projects. Flutter Driver is the legacy remote-control API that remains useful for interactive MCP sessions or maintaining older test suites. According to the flutter/skills source code, you only need the driver extension if you require external tooling or legacy compatibility.
Why do I need both a test file and a driver script?
The file in integration_test/ contains the actual test logic, assertions, and widget interactions. The driver script in test_driver/integration_test.dart acts as a minimal host required by the flutter drive command to initialize the test environment and report results. The integrationDriver() function in the host script forwards commands between the CLI and the app.
Can I run integration tests on web or desktop targets?
Yes. Use the -d flag with flutter drive to specify a device ID (for example, -d chrome for web). For web testing, you must first start chromedriver on port 4444. The same integration_test API works across Android, iOS, web, and desktop targets without code changes.
Do I need to use the Flutter Driver extension for new projects?
No. For standard end-to-end tests using only the integration_test package and WidgetTester, you do not need to call enableFlutterDriverExtension() or create a separate main_test.dart entry point. The extension is primarily required for MCP-driven interactive exploration or when migrating legacy flutter_driver tests that rely on the remote-control protocol.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →