flutter-add-integration-test

安装量: 7.1K
排名: #1172

安装

npx skills add https://github.com/flutter/skills --skill flutter-add-integration-test
Implementing Flutter Integration Tests
Contents
Project Setup and Dependencies
Interactive Exploration via MCP
Test Authoring Guidelines
Execution and Profiling
Workflow: End-to-End Integration Testing
Examples
Project Setup and Dependencies
Configure the project to support integration testing and Flutter Driver extensions.
Add required development dependencies to
pubspec.yaml
:
flutter pub
add
'dev:integration_test:{"sdk":"flutter"}'
flutter pub
add
'dev:flutter_test:{"sdk":"flutter"}'
Enable the Flutter Driver extension in your application entry point (typically
lib/main.dart
or a dedicated
lib/main_test.dart
):
Import
package:flutter_driver/driver_extension.dart
.
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
Key
s,
Text
nodes, and widget
Type
s.
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
_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
ValueKey
s 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 ) ; } ) ; } ) ; } Host Driver Script ( test_driver/integration_test.dart ) import 'package:integration_test/integration_test_driver.dart' ; Future < void

main ( ) =

integrationDriver ( ) ; Performance Profiling Driver Script ( test_driver/perf_driver.dart ) Use this driver script if you wrap your test actions in binding.traceAction() to capture performance metrics. import 'package:flutter_driver/flutter_driver.dart' as driver ; import 'package:integration_test/integration_test_driver.dart' ; Future < void

main ( ) { return integrationDriver ( responseDataCallback : ( data ) async { if ( data != null ) { final timeline = driver . Timeline . fromJson ( data [ 'scrolling_timeline' ] as Map < String , dynamic

, ) ; final summary = driver . TimelineSummary . summarize ( timeline ) ; await summary . writeTimelineToFile ( 'scrolling_timeline' , pretty : true , includeSummary : true , ) ; } } , ) ; }

返回排行榜