Create and run fast end-to-end tests using Moropo and Expo
Development••8 minutes read
Tom Riglar
Guest Author
In this tutorial blog you'll learn how to run faster end-to-end tests with Moropo and Expo.

This is a guest post from Tom Riglar - co-founder at Moropo, where he helps mobile teams implement Maestro and improve end-to-end testing for their iOS and Android apps.
...
End-to-end testing in mobile used to suck.
The old way:
- Change some code
- Push a pull request = 1 min
- Wait for the binary build = 15+ mins
- Wait for Detox/Appium tests to run = 20+ mins
- Get results on PR
With 30+ minute wait times, most teams didn’t bother with end-to-end tests—Moropo’s integration with Expo changes that.
The new way:
- Change some code
- Push a pull request = 1 min
- Use EAS Update to publish a change = ~4 mins
- Wait for Moropo tests to run = ~10 mins
- Get results on PR
With a 15-minute wait time, end-to-end testing provides a load more value:
As a developer, you can quickly get confidence that your code changes haven’t introduced regressive bugs. This lets you ship quicker and more often.
These are superpowers in a rapid development environment…
Here’s how you can do it yourself using Moropo and Expo.
But first, what is Moropo?
Moropo is a platform for building and running open-source Maestro tests in the cloud. It lets developers and QA testers work with iOS and Android directly in their web browser.
That means… no more “works on my machine”, no more flakiness between local tests and CI and no need for a MacBook for iOS testing.
Moropo and Expo testing tutorial
Here is an outline of the steps for testing with Moropo and Expo, followed by a detailed tutorial to set up this testing yourself:
- Part 1: Set up your Expo app
- Create an expo-dev-client
- Publish a branch
- Create a channel
- Part 2: Set up Moropo
- Create an account
- Upload your dev-client build
- Connect Expo
- Create a maestro test
- Add a CI trigger
- Part 3: Set up GitHub Action
- Create the action
- Add the Expo Update step
- Add the Moropo Trigger Test Run step
Part 1: Set up your Expo app
We will be using the EAS Update mechanism for these steps. If you’ve not used this feature before, you might want to read the Expo docs before continuing.
I’m working with iOS in this tutorial, but these steps work the same for Android.
It’s important to note that Moropo requires a simulator build (.app), so build accordingly.
Prerequisites:
- EAS account
- Apple Developer account (if working with iOS)
- Moropo account
- Some familiarity with the EAS Build and EAS Update workflows
Step A: Create an expo-dev-client
The first step is to create a development build. The following eas.json example contains a development profile called "development-simulator," which sets the ios simulator flag to true.
{"build": {"development-simulator": {"distribution": "internal","developmentClient": true,"ios": {"simulator": true}}}}
After adding the development profile, we can trigger a build against it by running:
eas build --profile development-simulator --platform ios
Once the build is complete, you should see something like this:
Click on the build link. This will take you to the EAS Dashboard where you can download the build. (see screenshot below)
Download and unzip the dev-client now - you’ll need this later!
Step B: Publish a branch
Using EAS update, publish to a branch to ensure Expo’s server has a copy of your bundle.
eas update --auto --branch expo-tutorial
The above command uses the --auto flag to auto-fill the branch name and the message. This flag will use the current Git branch as the branch name and the latest Git commit message as the message.
If you want to manually type the branch and message you can run something like:
eas update --branch version-1.0 --message "Fixes typo"
Step C: Create a channel
Ensure that you have a channel inside your expo project. I’d recommend using the same name as your branch name. These are the channels that will be available inside Moropo.
Part 2: Set up Moropo
Step A: Create an account on Moropo.com
Moropo is a cloud-based platform. Head to the sign-up form to create a free account.
Step B: Upload your dev-client build
Follow the onboarding steps. When you get to the upload step, select your build to upload.
Android: you’ll need to select your APK dev-client.
Important for iOS: you must zip up your app and use the .app.zip file extension.
Step C: Connect Expo
At the integration tab, press ‘continue’ to add Expo.
Generate an access token from the Expo dashboard.
Then paste this into Moropo.
Select your Expo account, then type in the project slug for your project. You can find this in the projects section of the Expo dashboard.
Search for release channels and select the one you created in Part 1.
Step D: Create a maestro test
Moropo will navigate you to the Test Editor, where you will create your first test.
Your first test will automatically be populated with a ‘launchApp’ command. Play this command, and the Expo dev client onboarding screen appears.
Instead, we want to launch with the bundle we pushed to our release channel in Part 1.
Moropo dynamically populates a variable with your release channel, so all we need to do is pass this to openLink like so:
- openLink:link: "${BUNDLEID}://expo-development-client/?url=${EXPORELEASECHANNEL}"
Run this command, and your app will load.
Now, create the rest of your test. Let's start with something simple, such as basic assertVisible.
Step E: Add a CI trigger
Next, we’ll configure Moropo to receive a CI trigger.
Go to ‘scheduled tests’ in the left-hand navigation bar.
Create a new schedule, selecting “CI-CD” as your trigger. Select the test you made, a device or two and the build you previously uploaded.
Finish this to generate your ‘scheduled test ID’; you’ll need this later when you connect to CI.
Part 3: Set up GitHub Action
In this part, we’ll connect GitHub to Expo and Moropo to run end-to-end tests automatically for each pull request.
Not using GitHub? You can set up any custom CI workflow using the Moropo web API with any platform.
Step A: Create the Action
The first section of our GHA will set up the action:
on: [pull_request]permissions:pull-requests: writejobs:tests:runs-on: ubuntu-lateststeps:- name: 🏗 Setup repouses: actions/checkout@v3- name: 🏗 Setup Nodeuses: actions/setup-node@v3with:node-version: 20.xcache: yarn
Step B: Add the Expo Update step
Next, we’ll set up EAS, install our dependencies and perform EAS Update.
- name: 🏗 Setup EASuses: expo/expo-github-action@v8with:eas-version: latesttoken: ${{ secrets.RIGLAR_EXPO_TOKEN }}- name: 📦 Install dependenciesrun: yarn install- name: 🚀 Create previewuses: expo/expo-github-action/preview@v8with:command: eas update --auto --branch ${{ github.event.pull_request.head.ref }}
Note: ensure you add your Expo access token to your GitHub secrets. Here mine is called RIGLAR_EXPO_TOKEN
Step C: Add the Moropo Trigger Test Run step
Finally, add in the Moropo trigger.
- name: Moropo - Trigger Mobile App Test Runuses: moropo-com/action-trigger-test-run@v2with:api_key: ${{ secrets.RIGLAR_MOROPO_API_KEY }}scheduled_test_id: <scheduled test id>sync: trueexpo_release_channel: https://u.expo.dev/<expo-project-id>?channel-name=${{ github.event.pull_request.head.ref }}&runtime-version=1.0.0&platform=ios
You must generate a Moropo API key from the Moropo settings page and add it as a GitHub secret. This lets the GitHub Action communicate with Moropo.
Ensure you replace the Scheduled Test ID with the one you generated in Part 2.
Copy the Expo Project UUID from your Expo dashboard into the expo_release_channel. You can find this on your project home page.
ROI of Moropo
Push up a new pull request and see your results roll in!
As GitHub has run my action previously, it’s cached some of the steps and took only 1m 16s to push my update to EAS
Moropo was equally fast, taking just 1m 50s to spin up a fresh emulator, run the test and pass back the results.
What’s next for Moropo?
Have questions? Need help with your setup? Join Moropo’s Discord or message me on Expo’s Discord.
In the future, we see Moropo as a great way for developers and QA testers to collaborate on mobile app quality.
We’re a huge fan of EAS and love how it’s made React Native development so much easier. Our goal is to provide a similar service to Maestro users. Right now, the framework is great but the tooling is lacking. Moropo is filling that gap.
Our team is experimenting with features to support visual regression checks, test case branching and more connections to 3rd party services. If there is a feature you’d like to see or try out, let us know.
-
P.S. Want to get better at Maestro tests? Check out my free email course: 7 tips for more reliable Maestro tests.


