In this tutorial, we'll cover the process of setting up and running integration tests in Flutter using the
integration_test
package. We'll use testing code for The Playlist app (available on Google Play). By the end of this tutorial, you'll have a solid understanding of how to perform end-to-end testing for your Flutter app.Setting up the Project for Integration Testing
First, you'll need to add theĀ
integration_test
Ā package to yourĀ pubspec.yaml
Ā file as a dev dependency:dev_dependencies: integration_test: sdk: flutter flutter_test: sdk: flutter
After adding the package, runĀ
flutter pub get
Ā to install it.Ā
Step 1: Setup test environment
Create a new file calledĀ
integration_test/app_test.dart
. In this file, import the necessary libraries:import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; import 'package:your_app_package/your_app.dart'; // Replace with the import to your main app file
Ā
Step 2: Write helper functions
Before diving into the main test, let's create some helper functions that will be used in the test, we use helper functions for reusability purpose:
createPlaylist
: Creates a new playlist
openPlaylistsPage
: Opens the playlists page
editPlaylistTitle
: Edits the playlist title
editPlaylistDate
: Edits the playlist date
deletePlaylist
: Deletes the playlist
We will expand on these later.
Ā
Step 3: Write the main test
Now, let's write the main test function that will use the helper functions to test the app's functionality. The provided code in the question can be used as a starting point:
void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); group('Test Playlist', () { testWidgets('create, edit, delete playlist', (tester) async { // Build our app and trigger a frame. const newPlaylistTitle = 'Test Playlist'; const editedPlaylistTitle = 'Edited Test Playlist'; const newPlaylistDate = '28'; app.main(); await tester.pumpAndSettle(const Duration(seconds: 1)); await createPlaylist(tester, newPlaylistTitle); expect(find.text(newPlaylistTitle), findsWidgets); await openPlaylistsPage(tester); await editPlaylistTitle(tester, newPlaylistTitle, editedPlaylistTitle); expect(find.text(editedPlaylistTitle), findsWidgets); await editPlaylistDate(tester, newPlaylistDate); await openPlaylistsPage(tester); expect(find.textContaining(newPlaylistDate), findsWidgets); await openPlaylistsPage(tester); await deletePlaylist(tester, editedPlaylistTitle); expect(find.text(editedPlaylistTitle), findsNothing); }); }); }
Ā
Helper Functions
Let's take a look at helper functions that can perform actions such as creating, editing, and deleting playlists. Here's a breakdown of each function:
createPlaylist
This function first taps the "Add Playlist" button, then enters the givenĀ
title
Ā into theĀ TextFormField
Ā and taps the "Create" button. It uses theĀ pumpAndSettle
Ā method to ensure the UI has time to update between interactions.createPlaylist(WidgetTester tester, String title) async { await tester.pumpAndSettle(const Duration(milliseconds: 200)); await tester .tap(find.byKey(const Key('addPlaylistButton'), skipOffstage: false)); await tester.pumpAndSettle(const Duration(milliseconds: 200)); // Fill in the new playlist form await tester.enterText(find.byType(TextFormField).first, title); await tester.tap(find.text('Create')); await tester.pumpAndSettle(const Duration(milliseconds: 200)); }
Ā
editPlaylistTitle
This function first taps on the playlist with the givenĀ
title
, then taps the edit icon in the app bar. It updates the playlist title with the providedĀ newTitle
Ā and taps the "Update" button.editPlaylistTitle(WidgetTester tester, String title, String newTitle) async { await tester.tap(find.text(title).first); await tester.pumpAndSettle(const Duration(milliseconds: 200)); // tap on edit icon in the topbar await tester.tap(find.byIcon(Icons.edit).first); await tester.pumpAndSettle(const Duration(milliseconds: 200)); // change the title of the playlist to "Edited Test Playlist" await tester.enterText(find.byType(TextFormField).first, newTitle); await tester.tap(find.text('Update')); await tester.pumpAndSettle(const Duration(milliseconds: 200)); }
Ā
editPlaylistDate
This function taps the edit icon in the app bar, then taps the lastĀ
TextField
Ā to change the date of the playlist. It selects theĀ newDate
Ā and taps the "OK" button. Finally, it taps the "Update" button.editPlaylistDate(WidgetTester tester, String newDate) async { // tap on edit icon in the topbar await tester.pumpAndSettle(const Duration(milliseconds: 200)); await tester.tap(find.byIcon(Icons.edit).first); await tester.pumpAndSettle(const Duration(milliseconds: 200)); // change the date of the playlist to "Edited Test Playlist" await tester.tap(find.byType(TextField).last); await tester.pumpAndSettle(const Duration(milliseconds: 200)); await tester.tap(find.text(newDate).first); await tester.pumpAndSettle(const Duration(milliseconds: 200)); await tester.tap(find.text('OK')); await tester.pumpAndSettle(const Duration(milliseconds: 200)); await tester.tap(find.text('Update')); await tester.pumpAndSettle(const Duration(milliseconds: 200)); }
Ā
deletePlaylist
This function first taps on the playlist with the givenĀ
playlistTitle
, then taps the delete icon in the app bar. It taps the "OK" button in the confirmation dialog to delete the playlist.deletePlaylist(WidgetTester tester, String playlistTitle) async { await tester.pumpAndSettle(const Duration(milliseconds: 200)); await tester.tap(find.text(playlistTitle).first); await tester.pumpAndSettle(const Duration(milliseconds: 200)); // tap on delete icon in the topbar await tester.tap(find.byIcon(Icons.delete).first); await tester.pumpAndSettle(const Duration(milliseconds: 200)); // tap on delete button in the dialog await tester.tap(find.text('OK')); await tester.pumpAndSettle(const Duration(milliseconds: 200)); }
Ā
openPlaylistsPage
This function navigates to the "Playlists" page by tapping on the "Playlists" text.
openPlaylistsPage(WidgetTester tester) async { await tester.pumpAndSettle(const Duration(milliseconds: 200)); await tester.tap(find.text("Playlists")); await tester.pumpAndSettle(const Duration(milliseconds: 200)); }
Ā
Running the Integration Test
The test function is wrapped inside aĀ
group
Ā called "Test Playlist". It tests the entire process of creating, editing, and deleting a playlist.To run the test on a real iOS/Android device or emulator, use the following command in your terminal:
flutter test integration_test/app_test.dart
Alternatively, you can specify the directory to run all integration tests:
flutter test integration_test
This command will run the app and integration tests on the target device.
You can also run the test by opening the Testing tab and click on āRun testā or āDebug testā.
Conclusion
This tutorial covers how to set up and run integration tests in Flutter using the
integration_test
package. Real working testing code from The Playlist app is used as a base, and each of the helper functions, as well as the main test function, are explained. By following these steps, you should now have a solid understanding of how to perform end-to-end testing on a Flutter app using integration tests.Sources:
Ā