Skip to content

Mobile App Testing Patterns

Your React Native app works flawlessly on the iPhone 15 Pro sitting on your desk. Then the crash reports roll in: Android 12 on Samsung Galaxy A13, iOS 16 on iPhone SE (2nd gen), and a tablet layout that overlaps every text element. Mobile testing is a combinatorial explosion — dozens of devices, multiple OS versions, varying screen sizes, and platform-specific behaviors. AI tools cannot test on every device, but they can generate the tests that cover the most ground.

  • Cross-platform test generation for React Native and Flutter applications
  • Device matrix strategies that maximize coverage without testing every permutation
  • Platform-specific testing patterns for gestures, navigation, and permissions
  • Responsive layout testing across screen sizes and orientations
  • AI prompts for generating Detox and Maestro test suites
Generate Detox E2E tests for our React Native app's onboarding flow:
Flow: Splash -> Welcome -> Permission Requests -> Profile Setup -> Home
1. Splash screen: Verify logo displays, auto-navigates after 2 seconds
2. Welcome: Swipe through 3 carousel pages, tap "Get Started"
3. Permissions: Handle push notification permission dialog (allow and deny paths)
4. Profile: Fill name, select avatar, tap "Complete"
5. Home: Verify the user name appears, main navigation tabs are visible
Platform-specific handling:
- iOS: Use system dialog matchers for permission requests
- Android: Use UiAutomator for permission dialogs
Test both:
- Happy path (all permissions granted)
- Permissions denied path (verify graceful degradation)
- Back navigation at each step
Save to /e2e/onboarding.e2e.ts

Detox gives you tight, code-level control; Maestro trades some of that control for declarative YAML flows that are far quicker to write and read — ideal for smoke tests and for QA folks who do not live in the codebase. A flow is just a list of commands against accessibility labels or visible text:

.maestro/login-smoke.yaml
appId: com.yourcompany.app
---
- launchApp:
clearState: true
- assertVisible: "Welcome back"
- tapOn: "Email"
- inputText: "qa@example.com"
- tapOn: "Password"
- inputText: "hunter2"
- tapOn: "Sign in"
- assertVisible:
id: "home-tab"
- takeScreenshot: login-success

Run it with maestro test .maestro/login-smoke.yaml. Ask the AI to bootstrap the flow from your screen labels:

Where each tool runs these flows differs in practice:

Run Detox and Maestro locally against a booted simulator/emulator while you iterate, using Agent mode to fix selectors the moment a flow fails. Keep the device and the Metro bundler running so re-runs are fast; Cursor’s checkpoints let you revert a broken test edit without losing the rest.

You cannot test on every device. Choose strategically.

“Detox tests pass on simulator but fail on real devices.” Simulators and emulators do not perfectly replicate real device behavior. Gestures, performance, and system dialogs behave differently. Run critical path tests on at least one real device through a cloud service (BrowserStack, AWS Device Farm).

“Tests are flaky due to animation timing.” Mobile animations cause timing issues. Disable animations inside the app process, not from the test: have your AppDelegate check for a launch arg the test passes (e.g. -disableAnimations) and call UIView.setAnimationsEnabled(false) — calling it from the E2E test itself has no effect because it runs in a separate process. On Android, set Developer options > Window/Transition/Animator scale to 0x on the emulator image, or rely on Detox’s built-in synchronization to wait out animations.

“Android tests behave differently across manufacturers.” Samsung, Xiaomi, and OnePlus add custom UI layers that affect system dialogs and navigation. Test on the top 3 manufacturers in your analytics, not just the stock Pixel emulator.

“Our CI is too slow for mobile tests.” Mobile test suites are inherently slower than web tests. Run smoke tests (3-5 critical flows) on every PR and the full suite nightly. Use cloud device farms for parallel execution.