How to Test React Native Apps with Maestro


React Native applications need to work consistently across iOS and Android, which makes testing critical. Traditional mobile testing tools often involve complex setup and dependency on emulators, which slows down the process.
Maestro uses YAML-based scripts that are easy to maintain, runs tests on real devices, and integrates with CI pipelines without heavy configuration. For React Native projects, Maestro helps validate user flows, catch UI issues early, and maintain stable test suites even as the app evolves.
This article explores how Maestro can be applied effectively for React Native testing.
Understanding Maestro Mobile Testing Framework
Maestro is an open-source mobile UI testing framework that uses YAML-based test definitions. This allows teams to write test scenarios in a structured, human-readable format. The framework focuses on stability and resilience, so tests are less likely to break when UI elements change.
At its core, Maestro provides three important capabilities for mobile app testing. Below are the key aspects that define how it works:
- YAML-based test scripts: Test cases are defined in YAML files, which are simpler to write and understand compared to code-heavy approaches. This makes the tests more maintainable and accessible to a wider team.
- Device-first execution: Maestro is built to run on real iOS and Android devices. It reduces reliance on emulators and helps capture behavior that matches real-world usage.
- Resilient element matching: Instead of depending on brittle locators, Maestro identifies UI elements in a way that adapts to structural changes, reducing test flakiness over time.
These characteristics make Maestro different from older mobile automation tools, where test maintenance often takes more time than test creation.
Benefits of Maestro for React Native Testing
React Native applications introduce unique testing needs because they share a single codebase across iOS and Android. Teams need a tool that can handle platform differences without making the process more complex. Maestro provides practical benefits that fit well with these requirements.
Here are the main advantages of using Maestro for React Native testing:
- Cross-platform consistency: A single test flow written in YAML can be executed on both iOS and Android devices, reducing duplication of effort.
- Simplified test creation: YAML-based syntax makes it easier to describe user journeys without extensive coding. This helps both developers and testers collaborate on writing tests.
- Lower maintenance effort: Resilient element matching ensures that small UI changes do not break entire test suites, reducing the time spent fixing tests.
- CI/CD integration: Maestro can be integrated into existing pipelines, so tests run automatically with every build. This allows teams to detect issues earlier in the development cycle.
- Real-device validation: Running on physical devices ensures that tests capture real-world performance and UI behavior, which is often missed on emulators.
Maestro Framework vs Traditional React Native Testing
Traditional testing for React Native applications often relies on tools like Appium or Detox. These frameworks are powerful but tend to require heavy setup, detailed locator strategies, and ongoing maintenance as the app evolves. Maestro approaches testing differently by focusing on simplicity, resilience, and readability.
Below are the key differences between Maestro and traditional React Native testing approaches:
- Setup and configuration: Traditional tools demand complex setup, SDK installations, and detailed configurations. Maestro has a lighter setup and runs with minimal dependencies.
- Test authoring: Appium and Detox rely on JavaScript or other programming languages for writing tests, which increases complexity. Maestro uses YAML, which is easier to learn and maintain.
- Locator strategy: Traditional tools depend on element locators like IDs, XPaths, or accessibility labels. These are prone to breaking with minor UI changes. Maestro uses a resilient matching mechanism that adapts better to evolving layouts.
- Execution environment: Traditional frameworks often encourage emulator-based testing during development. Maestro emphasizes real-device execution, ensuring tests reflect actual user conditions.
- Maintenance overhead: With traditional tools, small UI adjustments can cause large sections of the test suite to fail. Maestro’s design helps minimize such flakiness and lowers long-term maintenance costs.
Getting Started with Maestro
Before writing tests for React Native applications, teams need to set up Maestro in their development environment. The process is straightforward compared to other mobile automation tools but still requires a few steps to ensure smooth execution.
Here are the main steps to get started with Maestro:
- Install Maestro CLI: Maestro provides a command-line interface that serves as the primary way to run tests. It can be installed using Homebrew on macOS or a direct package download for other platforms.
- Connect a device: Maestro is designed to run on real devices. You can connect an iOS or Android device using USB, or run tests on a cloud-based device grid such as BrowserStack.
- Initialize a project: Using the maestro init command, you can set up the initial project structure. This generates folders and sample YAML files that act as templates for writing tests.
- Verify installation: Running a sample test included with the setup ensures that Maestro is correctly installed and connected to the device.
With these steps completed, teams are ready to start configuring their React Native applications for testing.
Configuring React Native Applications for Testing
Before running React Native tests with Maestro on BrowserStack App Automate (Beta), you need to configure both your app build and your test environment. This setup ensures that tests run reliably on real devices and interact with UI elements in a stable way.
The process involves preparing the application identifiers, making the UI testable, and uploading builds to BrowserStack.
Step 1: Update Application Identifiers
Maestro requires that your application identifiers are correctly set so that the uploaded builds align with the references in your test flows.
For Android (React Native CLI projects): Open the android/app/build.gradle file and update the applicationId:
android {
defaultConfig {
applicationId "com.example.app"
}
}
For iOS: In Xcode, go to Project Settings > Signing & Capabilities and update the Bundle Identifier.
For Expo projects: Modify the app.json file to set the bundle identifiers for both platforms:
{
"expo": {
"ios": {
"bundleIdentifier": "com.example.app"
},
"android": {
"package": "com.example.app"
}
}
}
Ensuring consistent identifiers prevents errors when running Maestro flows on BrowserStack devices.
Step 2: Add Test Identifiers to Components
React Native components need stable identifiers so Maestro can locate them across builds. The recommended approach is to add testID props. This avoids relying on text content or layout, which often change during development.
Example:
Sign In
With testID values in place, Maestro tests can use selectors like tapOn: “usernameInput” instead of depending on fragile text-based locators.
Step 3: Prepare the App Build for Upload
Once identifiers are configured, generate builds for testing:
- Android: produce a signed APK or AAB.
- iOS: create an IPA file with the correct provisioning profiles and entitlements.
Upload these builds to BrowserStack App Automate. Each test runs on a fresh device instance, so you don’t need to manage cleanup or provisioning locally.
Step 4: Configure BrowserStack Execution
Select the devices and OS versions you want to test on within BrowserStack. You can run tests on multiple devices in parallel, which helps shorten execution time when your test suite grows. If your app interacts with private or staging servers, enable BrowserStack Local to establish a secure tunnel between BrowserStack devices and your internal network.
Step 5: Validate and Extend
Run a sample Maestro flow on BrowserStack to verify the build, identifiers, and UI element mappings. Once confirmed, extend the test suite to cover more scenarios. BrowserStack provides video recordings, screenshots, and device logs in the App Automate dashboard, which help you debug failures and track coverage across different devices.
Writing Your First Maestro Test
After configuring your React Native app, the next step is to create a Maestro test flow. A flow describes the sequence of interactions and validations that will be executed on the app. Maestro uses YAML files for defining these flows, making them human-readable and easy to maintain.
Step 1: Create a Flow File
Create a new YAML file in your project, for example login_flow.yaml. Each flow starts with the appId of your application, which should match the identifiers configured earlier.
appId: com.example.app
---
- launchApp
This ensures that Maestro launches the correct application during execution.
Step 2: Define Interactions
Add steps that represent user actions, such as entering text, tapping a button, or verifying content. Each action is defined as a YAML step in sequence.
Example:
appId: com.example.app
---
- launchApp
- tapOn: "usernameInput"
- inputText: "testuser"
- tapOn: "passwordInput"
- inputText: "password123"
- tapOn: "loginButton"
- assertVisible: "Welcome"
This test launches the app, enters credentials, taps the login button, and verifies that a welcome message appears.
Step 3: Use Stable Selectors
To avoid flakiness, always target UI elements using stable identifiers rather than dynamic text. For React Native apps, selectors should reference testID values added during configuration.
For example:
- tapOn: "loginButton"
is more reliable than:
- tapOn: "Sign In"
Step 4: Run the Flow Locally
Before integrating with BrowserStack, run the flow on a local emulator or simulator to confirm that it executes correctly. Use the Maestro CLI:
maestro test login_flow.yaml
Step 5: Execute on BrowserStack
Upload your flow file to BrowserStack App Automate and run it against real devices. The execution is handled in the cloud, and results include video recordings, logs, and screenshots for debugging.
To run with BrowserStack, trigger a command such as:
maestro cloud --workspace . --flow login_flow.yaml
This command uploads the flow and connects it with the app build you uploaded earlier.
Step 6: Review Test Reports
After execution, open the BrowserStack dashboard to review outcomes. You will see step-level details, device logs, and media files that confirm whether the flow behaved as expected.
Common Maestro Commands for React Native
Maestro tests are written in YAML format, where each line represents a command. These commands drive interactions with React Native apps in a way that closely mirrors how users operate the application. Below are the most commonly used commands and how they work in practice.
1. Launch an App
The launchApp command starts the application under test.
- launchApp:
appId: "com.example.app"
2. Tap on Elements
The tapOn command simulates a user tap. It works best with testID attributes defined in React Native.
- tapOn:
id: "loginButton"
3. Input Text
The inputText command enters text into input fields.
- inputText:
id: "usernameInput"
text: "testuser"
4. Assert Element Visibility
Assertions validate that UI elements are present and visible.
- assertVisible:
id: "welcomeMessage"
5. Wait for Elements
The waitFor command is useful for dynamic React Native screens where elements appear after API responses.
- waitFor:
id: "dashboardScreen"
timeout: 5000
6. Swipe and Scroll
Maestro supports gestures for navigating through screens.
- swipe:
direction: "UP"
7. Reuse Flows
Flows can be modularized and reused across test cases to avoid duplication.
- runFlow:
file: "login_flow.yaml"
React Native Testing Challenges and Solutions
Testing React Native applications comes with unique challenges because of the hybrid nature of the framework. Below are common issues teams face along with practical fixes.
- UI inconsistency across platforms: React Native apps can behave differently on iOS and Android, making cross-platform validation critical. Running tests on real devices with BrowserStack App Automate helps identify and address these variations early.
- Flaky element locators: When tests rely on changing text or dynamic selectors, they often fail. Using testID props consistently in components allows Maestro scripts to interact reliably with the UI.
- Handling asynchronous content: Screens that load data asynchronously or have animations may appear unstable during tests. Applying Maestro’s waitFor command with appropriate timeouts ensures tests wait for elements before acting.
- Testing local development builds: Internal or staging apps are inaccessible to public devices. BrowserStack Local provides a secure tunnel, enabling tests on locally hosted builds without exposing them externally.
- Scaling test execution: Large test suites can take hours if run sequentially. Parallel execution across multiple devices with BrowserStack reduces runtime and delivers faster feedback.
Best Practices for Maestro Testing for React Native
To maximize the reliability and efficiency of Maestro tests on React Native apps, follow these practices that help teams improve test maintainability.
- Use stable identifiers: Assign testID props to all interactive elements. This makes tests more resilient to UI changes and reduces flakiness.
- Keep flows modular: Break test scenarios into smaller reusable flows. This simplifies maintenance and allows sharing steps across multiple test cases.
- Leverage real devices: Always execute tests on real devices rather than emulators when possible. Real hardware exposes platform-specific behaviors and ensures more accurate results.
- Implement wait strategies wisely: For screens with dynamic content or animations, apply Maestro’s waitFor commands. This prevents false failures caused by timing issues.
- Run tests in parallel: Distribute tests across multiple devices simultaneously using BrowserStack. Parallel execution shortens overall test runtime and accelerates feedback loops.
- Capture logs and media: Enable video recording, screenshots, and device logs in BrowserStack. These artifacts help diagnose failures quickly and provide visibility into test execution.
- Integrate with CI/CD pipelines: Trigger Maestro tests automatically in your build process using BrowserStack’s REST API. This ensures testing is part of every development cycle and reduces manual overhead.
- Validate early and often: Start with small flows to confirm setup correctness before scaling up. Early validation catches misconfigurations and reduces debugging time for larger suites.
Conclusion
Testing React Native apps effectively requires structured test design and reliable execution. Maestro’s YAML-based framework enables clear, modular flows with stable selectors and wait strategies for dynamic content, ensuring tests remain maintainable and resilient across UI changes.
BrowserStack App Automate enhances Maestro testing by providing access to real iOS and Android devices, parallel execution, secure local testing, and comprehensive reporting with videos, screenshots, and device logs. This combination ensures consistent, scalable, and reliable testing across multiple platforms and device configurations.

Contents
- Understanding Maestro Mobile Testing Framework
- Benefits of Maestro for React Native Testing
- Maestro Framework vs Traditional React Native Testing
- Getting Started with Maestro
- Configuring React Native Applications for Testing
- Step 1: Update Application Identifiers
- Step 2: Add Test Identifiers to Components
- Step 3: Prepare the App Build for Upload
- Step 4: Configure BrowserStack Execution
- Step 5: Validate and Extend
- Writing Your First Maestro Test
- Step 1: Create a Flow File
- Step 2: Define Interactions
- Step 3: Use Stable Selectors
- Step 4: Run the Flow Locally
- Step 5: Execute on BrowserStack
- Step 6: Review Test Reports
- Common Maestro Commands for React Native
- React Native Testing Challenges and Solutions
- Best Practices for Maestro Testing for React Native
- Conclusion
Subscribe for latest updates
Share this article
Related posts









