Maestro is a robust UI testing framework for Android and iOS applications. In this guide, we’ll walk you through the process of UI testing a Flutter app locally using Maestro, using the Blackhole Music app as our example.
This article provides a step-by-step guide on using Maestro for UI testing in Flutter, emphasizing the importance of configuring Flutter for precise testing with Maestro. Using the Blackhole Music app as an example, it covers setup and configuration. The piece concludes with a practical demonstration through a sample Maestro UI test.
This is a multi-part series. Upcoming parts revolve around UI testing the real-world Blackhole Music Flutter App.
Getting Started
1. Clone the Repository
Start by cloning the Blackhole Music App repository:
git clone https://github.com/thekharche/maestro-flutter-music-app
- Navigate to the Directory
After cloning, navigate into the directory:
cd maestro-flutter-music-app
3. Installation
Install the required packages:
flutter pub get
Running the Flutter Application in VS Code
After getting the code ready, the next step is to run your Flutter application to validate its functionality. Here’s a streamlined guide on how to achieve this using Visual Studio Code:
- Opening the Project
- Launch Visual Studio Code.
- Navigate to
File
->Open
, then select and open your Flutter project directory.
2. Starting the Emulator/Simulator
- Within VS Code, go to the View menu -> Command Palette (or press
Ctrl+Shift+P
on Windows/Linux,Cmd+Shift+P
on macOS). - Type
Flutter: Launch Emulator
and select it from the list. Choose an Android or iOS device from the list.
3. Running the Application
- Ensure your Flutter project is open and navigate to the
main.dart
file. - On the right top, you can see options to run the Flutter app with the play button as well as select emulator.
- You can also press
F5
to run the app. This will also enable debugging, allowing you to set breakpoints and inspect variables. UseCtrl + F5
to run without debugging. - Alternatively, navigate to the Run menu at the top and select Start Debugging or Run without Debugging.
4. Interacting with the Running Application
- The app will launch in the chosen emulator or connected device.
- Any code changes can be instantly reflected in the running app by clicking on a Flutter hot reload button.
Starting Up Maestro Studio
Run the command maestro studio
in your terminal, which will launch Maestro Studio in your web browser. The GUI allows for UI testing, visually and interactively.
Maestro Studio serves as a personal assistant designed to streamline the process of writing Maestro Flows. With its intuitive interface, users can effortlessly identify and interact with UI elements in their apps, use AI to auto-generate test commands, search for all the elements and many more niceties. The platform offers features such as visual selection of UI components
Configuring Flutter for effective Maestro UI testing
Note: While this section introduces Semantics
and explicitChildNodes
, their practical usage in UI testing will be extensively covered in Part 2 of this blog series.
In a scenario where your Flutter app features a list of songs, each with a title and subtitle, employing Semantics
and explicitChildNodes
becomes crucial for UI testing with Maestro Studio. This setup helps in accurately identifying and interacting with specific text elements during testing, ensuring that the title and subtitle for each song are correctly displayed and accessible. By wrapping each Text
widget with a Semantics
widget and setting explicitChildNodes
to true, you create a clear semantic boundary that Maestro Studio can recognize and interact with, making your UI tests more precise and reliable.
Notice below, the title and subtitle is not explicitly identifiable. Follow the blue box.
Original Code:
title: Text(
widget.songs[index].title.trim() != ''
? widget.songs[index].title
: widget.songs[index].displayNameWOExt,
overflow: TextOverflow.ellipsis,
),
subtitle: Text(
'${widget.songs[index].artist?.replaceAll('<unknown>', 'Unknown') ?? AppLocalizations.of(context)!.unknown} - ${widget.songs[index].album?.replaceAll('<unknown>', 'Unknown') ?? AppLocalizations.of(context)!.unknown}',
overflow: TextOverflow.ellipsis,
),
Adding semantics to your Flutter app and setting explicitChildNodes: true
can enhance accessibility and allow for more effective UI testing. Here’s a step-by-step guide to help you achieve that.
Adding Semantics
The Semantics
widget in Flutter is used to annotate widgets with a description of their meaning, which is essential for accessibility purposes. When you wrap a widget with Semantics
, you can provide a meaningful label to describe the widget.
Configuring explicitChildNodes
for Precise UI Testing
The explicitChildNodes
property when set to true, directs Flutter to treat each child of the Semantics
widget as a separate entity in the semantic tree, instead of merging them into one node. This is beneficial for UI testing as it allows for more precise interaction and verification of individual widgets within a complex widget tree.
Note the blue box.
When both a semanticsLabel
and a text label are present, the semanticsLabel
is given priority.
Code After Configuration:
title: Semantics( // ADDED
explicitChildNodes: true, // ADDED
child: Text(
widget.songs[index].title.trim() != ''
? widget.songs[index].title
: widget.songs[index].displayNameWOExt,
overflow: TextOverflow.ellipsis,
semanticsLabel: "${widget.songs[index].title}", // ADDED
),
),
subtitle: Semantics( // ADDED
explicitChildNodes: true, // ADDED
child: Text(
'${widget.songs[index].artist?.replaceAll('<unknown>', 'Unknown') ?? AppLocalizations.of(context)!.unknown} - ${widget.songs[index].album?.replaceAll('<unknown>', 'Unknown') ?? AppLocalizations.of(context)!.unknown}',
overflow: TextOverflow.ellipsis,
),
),
Sample Maestro UI Test
To ensure our setup is functioning correctly, let’s create a basic Maestro Flow.
- Setting up the Test
Create a flow.yaml
file in the .maestro
directory at the root of your project. Add the following content:
appId: com.shadow.blackhole
---
- launchApp:
clearState: true
- assertVisible: "Skip"
2. Run the Test
Go to your terminal and execute:
maestro test .maestro/flow.yaml
Stay Tuned
The next part of the series will cover end-to-end UI testing of a Music App made in Flutter!
References
Maestro and Flutter:
Blackhole Music App Source Code:
Maestro Studio:
🎹