Guide · Updated July 2026

How to Test an Expo App

Testing an Expo app is a ladder. Each rung — Expo Go, a development build on a simulator, a dev build on your actual phone, internal distribution, TestFlight — catches a class of bugs the rung below it can't. Most shipping problems trace back to skipping rungs: the app was only ever run in Expo Go, or only on a simulator, and the first real device it met belonged to a user.

This guide covers the whole ladder as it stands in mid-2026 (current Expo SDK: 55, on React Native 0.83, with the New Architecture as the default — checked July 2026), plus the gap none of these tools close: your coding agent writes the code but never sees it running.

Expo Go vs development builds

Expo Go is the sandbox app from the App Store and Play Store that runs your JavaScript inside a prebuilt shell. A development build is your own app — your bundle ID, your native modules — with Expo's dev tooling compiled in.

Expo GoDevelopment build
InstallApp Store / Play StoreYou build it (EAS Build or locally)
Native modulesOnly the set bundled into GoAnything in your package.json
Config plugins, custom native codeNoYes
SDK versionsOne version per Go releaseWhatever your project uses
App identity (bundle ID, icon, push)Expo's, not yoursYours
Fidelity to the app you'll shipApproximationThe real thing, plus a dev menu
Good forThe first hours of a projectEverything after that

Expo Go stops being enough the moment you add a library with native code that Go doesn't bundle, touch a config plugin, or need your app's real identity — push notifications, deep links, in-app purchases. Expo itself now describes Go as an educational tool for getting started and recommends development builds for anything you intend to ship (checked July 2026).

There's also a dependency you don't control: Expo Go is someone else's App Store app. In May 2026, the Expo Go release supporting SDK 55 sat waiting on App Store approval while SDK 55 was already out — Expo's published workarounds were the simulator version of Go, a personal Go build via eas go, and, again, switching to development builds. When your test environment is another company's app, its availability isn't in your hands.

Creating a dev build is one command per platform:

# Cloud build (no Xcode or Android Studio needed)
eas build --profile development --platform ios

# Or locally, if you have the native toolchains
npx expo run:ios
npx expo run:android

Once it's installed, npx expo start connects to it exactly like Expo Go used to — the workflow feels the same, the fidelity isn't.

Simulators and emulators

The iOS Simulator (via Xcode, Mac only) and Android Emulator (via Android Studio, any OS) are where day-to-day iteration happens. With a dev build installed, run npx expo start and press i or a to launch.

What they're good at: fast reload cycles, checking layouts across screen sizes, and debugger access — see the React Native debugging guide for the full DevTools workflow.

What they can't tell you: real camera and sensor behavior, true performance (your laptop's CPU flatters everything), cellular and flaky-network behavior, real push-notification delivery, and how the app feels under a thumb. A simulator-only testing habit is how "works on my machine" comes to mobile.

EAS Build and internal distribution

EAS Build compiles your app in Expo's cloud — which means you can produce a real iOS app without owning a Mac. For getting builds onto physical devices before TestFlight, use internal distribution:

  1. Register test devices: eas device:create walks each iPhone through UDID registration with a link.
  2. Build with a profile that has "distribution": "internal" — commonly the preview profile.
  3. EAS gives you an install link; testers open it on the device. Android testers just get an APK link, no registration needed.

No store review, no waiting. This is the fastest route from "it works in the simulator" to "it works on five real phones."

TestFlight for Expo apps

For a wider iOS beta, TestFlight is the standard path. You'll need an Apple Developer Program membership. Then:

eas build --profile production --platform ios
eas submit --platform ios

Internal testers (up to 100 people on your App Store Connect team) get builds immediately; external testers (up to 10,000) require a one-time Beta App Review. Builds expire 90 days after upload. TestFlight also gives testers a built-in way to send you marked-up screenshots — how that works, and where the feedback lands, is covered in TestFlight Feedback, Explained.

EAS Update: pushing fixes without a rebuild

EAS Update delivers JavaScript and asset changes over the air to builds already in the field — including TestFlight builds. Fix a JS bug, run eas update, and existing installs pick it up on next launch. No store review, no new binary. SDK 55 also made updates dramatically smaller to download via Hermes bytecode diffing (checked July 2026).

The boundary: an update can only change JavaScript and assets. Anything native — a new library with native code, a config-plugin change, an SDK upgrade — changes your runtime version and requires a new build through the whole ladder again. EAS Update is how you ship the fix fast; it's not how you skip testing.

The verification gap

Here's what the ladder doesn't solve. Every tool above gets your app onto a device. None of them get what happens on that device back to the thing writing your code.

Your agent — Claude Code, Codex, Cursor — writes the fix, but it can't see the running app. It doesn't know the button is under the home indicator, that the list stutters on a mid-range Android phone, or that the fix it just shipped moved the bug instead of killing it. So you become the bridge: screenshot the device, describe what's wrong, paste, repeat — the loop from vibe debugging, run manually.

Vibejar closes that specific gap for your own app: capture the bug on the device, circle what's wrong, and it lands in your agent with full visual context — then the agent ships the fix and returns before/after proof. It's the missing rung between "spotted on device" and "fixed in code."

For everything else in the tooling landscape — device clouds, E2E automation, capture SDKs — see the mobile app testing tools roundup.

Frequently asked questions

Can I test an Expo app without a Mac?

Mostly, yes. EAS Build compiles iOS apps in the cloud, so you can produce real builds and distribute them to physical iPhones via internal distribution or TestFlight without touching Xcode. Android testing is fully Mac-free. The one thing you can't run without a Mac is the iOS Simulator — so budget a real iPhone for iOS testing.

Is Expo Go enough to test my app?

Only at the very start. Expo Go can't run custom native code or config plugins, uses Expo's app identity instead of yours, and tracks a single SDK version. Expo itself positions Go as a learning tool and recommends development builds for any app you plan to ship. Treat Go as a sketchpad; test on a dev build.

How do I put an Expo app on TestFlight?

Build a production iOS binary with EAS Build, then run eas submit to upload it to App Store Connect. Internal testers can install it right away; external testers need a one-time Beta App Review first. You'll need an Apple Developer Program membership, but not a Mac.

Can EAS Update fix any bug?

No — it can only change JavaScript and assets. That covers most logic and UI bugs, which is why it's so useful for fast fixes. Anything that touches native code, adds a native dependency, or changes your runtime version requires a new build, and for iOS users on TestFlight or the App Store, a new upload.

Keep reading