Maestro for Everyone
Complex workflows in mobile application development have made automated testing a necessity. And although End to End testing patterns are a godsend, they can be a pain to work with in a mobile app development environment. That’s where Maestro comes in. It is an open-source, mobile UI automation framework, designed for simplicity and effectiveness. It uses a flow-based model, where each flow is a sequence of user actions.
And the best part? Even non-technical users can write tests with it!
At Krumware, like many small teams, everyone wears multiple hats. Our apps are complex, and testing them thoroughly is essential - but we don’t have a dedicated QA team (yet). Thanks to Maestro’s human-readable syntax and straightforward structure, people from non-technical backgrounds are able to contribute to testing alongside developers.
It’s this accessibility that makes Maestro stand out.
Maestro Setup
Setup for Maestro is pretty straightforward. If you’re trying to test an iOS app, you’ll need macOS. For Android app testing, you’ll need Linux or Windows with WSL. You can run Maestro using its CLI, its Studio or in your CI. Maestro supports testing on Android emulators (.apk) and iOS simulators (.app).
Note: Maestro requires Java 17 or higher to be installed on your system.
To install Maestro, run the following command:
curl -L https://get.maestro.mobile.dev | bash
Alternatively, you can use Homebrew if you’re using macOS:
brew tap mobile-dev-inc/tap
brew install maestro
That's it!
If you’re a non-technical reader and you’re already lost – don’t worry! Maestro provides additional how-tos and walkthroughs to get your app ready to test.
How do I test my app with Maestro?
Now that you’ve installed Maestro and the app that you want to test, it’s time to start testing.
Maestro relies on user-written flows to perform the actions that you want to test. Think of Maestro as some person using your app for the first time. All you have to do is provide them with step-by-step instructions to navigate certain parts of your app.
Let’s start with a relatively simple user flow: Login.
Everyone is familiar with the standard login flow for most apps:
- Tap the “Login” button on the screen
- Tap the “Email Address” field, and type in your email address
- Tap the “Password” field, and type in your password
- Tap the “Login” button to proceed
Assuming you typed your email and password correctly, you’re automatically redirected to the landing page.
An example flow to test your app’s login functionality might look like this:
appId: com.example.app
---
- tapOn: "LOGIN"
- assertVisible: 'LOGIN'
- tapOn: "Email Address"
- inputText: ${EMAIL_ADDRESS}
- tapOn: "Password"
- inputText: ${PASSWORD}
- tapOn: "LOGIN"
- assertVisible: 'Welcome to my app!'
Notice the placeholders ${EMAIL_ADDRESS} and ${PASSWORD} – these come from environment variables, allowing you to test multiple scenarios just by changing your env file. For non-technical beginners, you can replace ${EMAIL_ADDRESS} and ${PASSWORD} with a real email address and password. In this example, the placeholders would allow you to quickly test any Email/Password combination without having to re-write the entire flow for each individual combination. Once you get more comfortable writing tests, you’ll quickly discover how much more efficient it is to use placeholders and variables whenever you can.
Readability That Anyone Can Follow
If you read the example flow above without any context or technical background, you could probably understand the gist of what each step in the flow is supposed to do. One of Maestro’s biggest strengths is readability. You don’t need to be a developer or a QA engineer to understand what’s happening in a flow. Each step mirrors how a real user interacts with your app, written in plain English.
Managing Complex Workflows
Our previous login flow example is about as basic as you can get. But maybe you don’t want your automated test to end there. Suppose you want to test additional user actions after logging in. Fortunately, Maestro makes it easy to reuse common, repeatable flows and import them into other test flows.
For example, maybe you want to test the following user journeys in your app:
Log in → Open the Privacy Policy page
Log in → Update My Display Name in Account Settings
Log in → Log out
Notice each of these flows includes Log in. The steps that a user takes to log in to your app are always the same. Instead of rewriting every step of Log in for each of the flows above, Maestro allows you to define the actions for Log in as a separate reusable flow file. You can use that separate Log in flow file we created in our very first example, and add it to the flows above. This prevents you from having to rewrite the same steps of the Log in flow over and over. Now the only new actions you have to write are for the flows in the second part of your journeys.
You can continue to use this strategy as your test flows become increasingly complex.
For example, imagine one flow goes through:
Screen A → Screen B → Screen G → Screen L
and another goes through:
Screen A → Screen C → Screen B → Screen G
Let’s assume that each Screen requires the user to perform some standard combination of actions to proceed to the next screen. Since both flows visit Screen B and Screen G, you can define the actions for each of those screens as separate reusable flow files, and import them into your main flows.
This keeps your parent flow high-level and readable, while the individual screen logic stays modular.
Maestro’s official blog has a great article on structuring E2E tests like this which is definitely worth checking out.
Final Thoughts
Maestro bridges a gap that’s often overlooked in mobile testing by making E2E testing accessible to everyone.
It only takes a couple of hours for a non-technical user to grasp the basics of Maestro. Once you master the basic principles, you can start expanding into more advanced features. For example, Maestro also supports commands like repeat and evalScript, which let you build dynamic flows that can adapt during execution. This flexibility allows you to handle more complex test cases without bloating your YAML files. And if you ever hit a technical wall, that’s where developers can jump in to extend the flows further.
Maestro allows our technical and non-technical team members to collaborate effectively, leading to faster and more reliable app testing. For small teams like ours, that’s invaluable.