E2E Testing for Expo Apps: Automated Runs on Every EAS Build
How to run e2e tests on Expo apps: build an iOS Simulator app with EAS, hand it to an AI testing agent, and get pass/fail checks with recordings on every pull request. No Detox, no macOS runners.

How e2e testing works for Expo apps
End-to-end testing an Expo app means running the real app binary, in a real simulator, through the flows your users actually perform: onboarding, login, the core loop. Historically that meant Detox or Maestro plus your own simulator infrastructure, which is exactly the part most Expo teams never get around to standing up. CI needs macOS runners for iOS simulators, the tooling needs native build configuration, and the tests need maintenance every time the UI shifts.
The setup in this post takes a different path: EAS builds the iOS Simulator app, which it already does well, and TesterArmy takes the artifact from there. The agent installs the build in a cloud simulator and runs your saved test flows against it, described in plain English rather than test code. Runs happen on every pull request, and results come back as GitHub checks with recordings and screenshots. There is no simulator fleet to maintain and no test framework to configure. One honest boundary to know up front: runs execute on simulators and emulators, which covers UI and flow regressions well, and does not replace on-device testing for hardware-specific behavior.
More on the setup for plain React Native projects (without EAS) is in React Native e2e testing without Detox, and the product page for this stack is Expo app testing.
Most Expo projects already use EAS as the place where native builds happen. It builds the app, stores the artifact, and can run workflows around that build.
That makes it a good place to add mobile QA. TesterArmy can take the iOS Simulator build from EAS, install it in a cloud simulator, and run your saved mobile tests against it.
You do not have to maintain a macOS runner, keep simulators warm, clean up uploaded artifacts, or write your own polling loop. For JavaScript-only changes, you can also use Expo Repack later and avoid a full native rebuild when the native runtime did not change.
Let's wire it up.
What EAS gives us
EAS already owns the native build step, so we should not duplicate that work somewhere else.
For TesterArmy, the important detail is the artifact type. We need an iOS Simulator .app build, not an .ipa.
An .ipa is meant for physical devices. A simulator run needs a simulator app bundle.
In EAS, the profile looks like this:
eas.json
Once EAS produces that .app, the workflow can upload it to TesterArmy and start a saved mobile test group.
What TesterArmy handles
The EAS workflow should stay simple. It only needs to orchestrate five things:
- Build the iOS Simulator app.
- Download the
.appartifact. - Upload the app to TesterArmy.
- Run the selected mobile test group.
- Delete the temporary app upload when the run finishes.
TesterArmy handles the rest:
- Cloud simulator provisioning
- App installation
- Agent-driven mobile test execution
- Screenshots, videos, and run artifacts
- Result polling
- GitHub checks and PR comments
That split is the whole integration. EAS gives us a build. TesterArmy runs it.
The required values
The workflow needs three values from TesterArmy.
| Environment variable | What it points to |
|---|---|
TESTERARMY_API_KEY | API key from Profile -> API Keys |
TESTERARMY_PROJECT_ID | Project ID from Project Settings |
TESTERARMY_GROUP_ID | Group ID for the mobile tests you want to run |
Keep TESTERARMY_API_KEY as an EAS secret or sensitive environment variable. Do not expose it through EXPO_PUBLIC_*, and do not commit it.
The project ID and group ID are not sensitive in the same way, but keeping all three values in the EAS environment makes the workflow easier to reuse across projects.
Adding the workflow
The basic workflow has three jobs.
First, build the simulator app:
.eas/workflows/testerarmy-mobile-tests.yml
Next, download the EAS artifact and upload it to TesterArmy:
.eas/workflows/testerarmy-mobile-tests.yml
Finally, run the saved test group with the uploaded app ID:
.eas/workflows/testerarmy-mobile-tests.yml
The full copy-paste version is in the Expo EAS docs.
Getting PR feedback
When this runs on a pull request, TesterArmy can create a GitHub check and leave a PR comment. Reviewers get the normal pass/fail signal, plus links to the run details, screenshots, videos, and logs.
To enable that, connect your TesterArmy project to the GitHub repository from the project Integrations tab.
After that, pass the commit SHA and PR number from the EAS workflow:
On push events, TesterArmy attaches the check to the commit. On pull requests, it can attach the check and the PR comment.
Using Expo Repack
The basic workflow runs a full simulator build every time. Start there. It is slower, but it removes a lot of variables while you are setting up the integration.
Once that is stable, you can make the workflow faster with EAS fingerprint and Expo Repack. This is useful when a pull request changes JavaScript only and the native runtime is still compatible.
The optimized workflow calculates the native runtime fingerprint, looks for a compatible simulator build, and repacks it with the current JavaScript bundle when the native layer did not change.
You still test the code from the branch, but you do not pay for a full native rebuild on every PR.
That workflow variant is included in the Expo EAS docs. Treat it as an optimization, not the first thing to debug.
Common mistakes
The most common issue is uploading the wrong artifact.
TesterArmy needs an iOS Simulator .app build. If the workflow uploads an .ipa, the run cannot install it in the simulator.
The second issue is running a group that does not contain mobile tests. Before adding EAS, run the mobile test manually from the dashboard once. Check that the app upload works, the test passes, and the test is in the group you plan to call from CI.
The third issue is missing GitHub integration. Tests still run without it, but PR comments and commit checks need the TesterArmy project to be connected to the repository.
That's a wrap
Expo EAS already knows how to build your app. TesterArmy just needs the simulator artifact.
The setup is: create an iOS Simulator build profile, add the EAS workflow, configure the three environment variables, and run the saved test group on every PR.
If you want the exact copy-paste setup, start with the Expo EAS integration docs. If you still need to create your first mobile test, start with App Uploads.
Frequently asked questions
Can you run e2e tests on Expo apps without Detox? Yes. Build an iOS Simulator app with EAS and run it with an agent-based platform like TesterArmy. Detox requires native build integration and test code in your repo; the agent approach needs the .app artifact and plain-English flow descriptions. The practical walkthrough is in our React Native guide.
Do I need an .ipa or an .app build for testing? For simulator runs you need an iOS Simulator .app bundle, produced by an EAS profile with the simulator flag. An .ipa targets physical devices and will not install in a simulator.
Does this work with Expo Repack for JS-only changes? Yes. Once the basic workflow is stable, Repack lets you skip full native rebuilds when only JavaScript changed, which makes the PR loop substantially faster. The post covers when it is safe to use.
What does the pull request actually see? A GitHub check plus a PR comment with pass/fail per flow, links to the run, screenshots, and a full video recording of the simulator session.


