Configures Flutter Driver for app interaction and converts MCP actions into permanent integration tests. Use when adding integration testing to a project, exploring UI components via MCP, or automatin
Configures Flutter Driver for app interaction and converts MCP actions into permanent integration tests. Use when adding integration testing to a project, exploring UI components via MCP, or automating user flows with the integration_test package.
Download skills/flutter-add-integration-test/SKILL.md from the publisher, or copy the path and open the repository. PlugMCP lists the skill and does not host the file.
Where does flutter-add-integration-test live?
The publisher keeps it at https://github.com/flutter/agent-plugins.
Which agents can use flutter-add-integration-test?
Claude, Cursor, Codex, and Grok Build can read a SKILL.md you add from the publisher's repository. Grok Bot installs it when you send the skill's GitHub folder link in a chat.
From the publisher
SKILL.md
name
flutter-add-integration-test
description
Configures Flutter Driver for app interaction and converts MCP actions into permanent integration tests. Use when adding integration testing to a project, exploring UI components via MCP, or automating user flows with the integration_test package.
Call enableFlutterDriverExtension(); before runApp().
Add Key parameters (e.g., ValueKey('login_button')) to critical widgets in the application code to ensure reliable targeting during tests.
Interactive Exploration via MCP
Use the Dart/Flutter MCP server tools to interactively explore and manipulate the application state before writing static tests.
Launch: Execute launch_app with target: "lib/main_test.dart" to start the application and acquire the DTD URI.
Inspect: Execute get_widget_tree to discover available Keys, Text nodes, and widget Types.
Interact: Execute tap, enter_text, and scroll to simulate user flows.
Wait: Always execute waitFor or verify state with get_health when navigating or triggering animations.
Troubleshoot Unmounted Widgets: If a widget is not found in the tree, it may be lazily loaded in a SliverList or ListView. Execute scroll or scrollIntoView to force the widget to mount before interacting with it.
Test Authoring Guidelines
Structure integration tests using the flutter_test API paradigm.
Create a dedicated integration_test/ directory at the project root.
Name all test files using the <name>_test.dart convention.
Initialize the binding by calling IntegrationTestWidgetsFlutterBinding.ensureInitialized(); at the start of main().
Load the application UI using await tester.pumpWidget(MyApp());.
Trigger frames and wait for animations to complete using await tester.pumpAndSettle(); after interactions like tester.tap().
Assert widget visibility using expect(find.byKey(ValueKey('foo')), findsOneWidget); or findsNothing.
Scroll to specific off-screen widgets using await tester.scrollUntilVisible(itemFinder, 500.0, scrollable: listFinder);.
Conditional Logic for Legacy flutter_driver:
If maintaining or migrating legacy flutter_driver tests, use driver.waitFor(), driver.waitForAbsent(), driver.tap(), and driver.scroll() instead of the WidgetTester APIs.
Execution and Profiling
Execute tests using the flutter drive command. Require a host driver script located in test_driver/integration_test.dart that calls integrationDriver().
Conditional Execution Targets:
If testing on Chrome: Launch chromedriver --port=4444 in a separate terminal, then run:
flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart -d chrome
If testing headless web: Run with -d web-server.
If testing on Android (Local): Run flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart.
If testing on Firebase Test Lab (Android):
Build debug APK: flutter build apk --debug
Build test APK: ./gradlew app:assembleAndroidTest
Upload both APKs to the Firebase Test Lab console.
Workflow: End-to-End Integration Testing
Copy and follow this checklist to implement and verify integration tests.
Task Progress: Setup
Add integration_test and flutter_test to pubspec.yaml.
Inject enableFlutterDriverExtension() into the app entry point.
Assign ValueKeys to target widgets.
Task Progress: Exploration
Run launch_app via MCP.
Map the widget tree using get_widget_tree.
Validate interaction paths using MCP tools (tap, enter_text).
Task Progress: Authoring
Create integration_test/app_test.dart.
Write test cases using WidgetTester APIs.
Create test_driver/integration_test.dart with integrationDriver().
Task Progress: Execution & Feedback Loop
Run flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart.
Feedback Loop: Review test output -> If PumpAndSettleTimedOutException occurs, check for infinite animations -> If widget not found, add scrollUntilVisible -> Re-run test until passing.
Examples
Standard Integration Test (integration_test/app_test.dart)
import 'package:flutter/material.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 on the floating action button, verify counter', (tester) async {
// Load app widget.
await tester.pumpWidget(const MyApp());
// Verify the counter starts at 0.
expect(find.text('0'), findsOneWidget);
// Find the floating action button to tap on.
final fab = find.byKey(const ValueKey('increment'));
// Emulate a tap on the floating action button.
await tester.tap(fab);
// Trigger a frame and wait for animations.
await tester.pumpAndSettle();
// Verify the counter increments by 1.
expect(find.text('1'), findsOneWidget);
});
});
}