# How to Add Integration Tests Using Flutter Driver and the integration_test Package

> Learn to add integration tests in Flutter using Flutter Driver and the integration_test package. Write and execute tests efficiently with our guide.

- Repository: [Flutter/skills](https://github.com/flutter/skills)
- Tags: how-to-guide
- Published: 2026-05-09

---

**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`](https://github.com/flutter/skills/blob/main/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`](https://github.com/flutter/skills/blob/main/pubspec.yaml). You need both `integration_test` and `flutter_test` from the Flutter SDK.

```yaml

# 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.

```dart
// 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.

```dart
// 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.

```dart
// 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.

```bash
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:

```bash
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_test` and `flutter_test` to `dev_dependencies` in [`pubspec.yaml`](https://github.com/flutter/skills/blob/main/pubspec.yaml)
- Enable the driver extension by calling `enableFlutterDriverExtension()` in `lib/main_test.dart` when legacy or MCP support is needed
- Author tests in `integration_test/app_test.dart` using `IntegrationTestWidgetsFlutterBinding.ensureInitialized()` and the `WidgetTester` API
- Provide a host driver script at `test_driver/integration_test.dart` that delegates to `integrationDriver()`
- 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.