React Native Testing
Test React Native mobile applications using the rn-testing MCP tools with Maestro, Detox, or Appium frameworks.
MCP Tools Available:
- •
maestro_run_flow/maestro_test- YAML-based mobile UI testing - •
detox_test- Gray-box React Native testing - •
appium_start_session/appium_find_element/appium_tap/appium_input_text- Cross-platform WebDriver automation - •
get_test_results- View test execution history
Helper Scripts Available:
- •
scripts/with_device.py- Manage device/emulator lifecycle - •
scripts/generate_flow.py- Generate Maestro YAML flows from templates - •
scripts/run_test_suite.py- Run multiple tests with formatted output - •
scripts/capture_screen.py- Capture screenshots during testing
Always run scripts with --help first to see usage. These scripts handle complex workflows reliably without cluttering context.
Decision Tree: Choosing Your Testing Approach
User task → Which framework should you use?
│
├─ New to mobile testing / Working with AI agents?
│ └─ Use Maestro (simplest, native MCP support)
│
├─ React Native-only project with source code access?
│ └─ Use Detox (fastest for RN, automatic synchronization)
│
└─ Multi-framework app or black-box testing?
└─ Use Appium (most flexible, cross-platform)
Once framework is chosen → What's your goal?
│
├─ Write new test?
│ ├─ Maestro → Create YAML flow file, then use maestro_run_flow
│ ├─ Detox → Create .test.js file, then use detox_test
│ └─ Appium → Start session, find elements, interact
│
├─ Run existing tests?
│ ├─ Maestro → Use maestro_test with flow paths
│ ├─ Detox → Use detox_test with configuration
│ └─ Appium → Execute session workflow
│
└─ Debug test failure?
└─ Use get_test_results to view recent executions
Quick Start: Maestro (Recommended)
Maestro is the recommended framework for AI agents due to its simplicity and native MCP support.
1. Create a Flow File
Option A: Generate from template (fastest)
python scripts/generate_flow.py login --app-id com.myapp --output flows/login.yaml
Option B: Write manually
Save as flows/login.yaml:
appId: com.myapp --- - launchApp - tapOn: "Login" - inputText: "user@example.com" - tapOn: "Password Field" - inputText: "password123" - tapOn: "Submit" - assertVisible: "Welcome Screen"
React Native Tip: Use testID props in your components to make elements easily targetable:
<Button testID="login-button" title="Login" />
Then reference in Maestro:
- tapOn:
id: "login-button"
2. Run the Flow
Option A: With device management (recommended)
python scripts/with_device.py --platform android --device "Pixel_7_API_34" -- \ maestro test flows/login.yaml
Option B: Use MCP tool directly (device must be running)
maestro_run_flow({
flow_file: "flows/login.yaml",
response_format: "markdown"
})
3. View Results
get_test_results({
framework: "maestro",
limit: 5
})
For more Maestro patterns, see maestro-patterns.md
Maestro Workflows
Pattern 1: Single Flow Testing
Use when: Testing a specific user scenario (login, checkout, onboarding)
# Generate flow from template python scripts/generate_flow.py login --app-id com.myapp --output flows/login.yaml # Run with device management python scripts/with_device.py --platform android --device "Pixel_7_API_34" -- \ maestro test flows/login.yaml
Or use MCP tools:
maestro_run_flow({
flow_file: "flows/checkout.yaml",
app_id: "com.myapp" // optional
})
Pattern 2: Test Suite Execution
Use when: Running multiple test scenarios or regression testing
# Run suite with formatted output python scripts/run_test_suite.py flows/ --stop-on-failure
Or use MCP tools:
maestro_test({
flow_paths: [
"flows/login.yaml",
"flows/navigation.yaml",
"flows/checkout.yaml"
]
})
Pattern 3: Continuous Development
Use when: Developing tests iteratively
maestro_test({
flow_paths: ["flows/feature.yaml"],
continuous: true // Reruns on file changes
})
Pattern 4: Environment-Specific Testing
Use when: Testing against different API endpoints or configurations
maestro_run_flow({
flow_file: "flows/api-test.yaml",
env: {
"API_URL": "https://staging.api.com",
"API_KEY": "test-key"
}
})
Detox Workflows
Prerequisites
- •Detox CLI installed:
npm install -g detox-cli - •
.detoxrc.jsconfiguration file in project - •App built for testing:
detox build --configuration ios.sim.debug
Pattern 1: Run All Tests
detox_test({
configuration: "ios.sim.debug"
})
Pattern 2: Run Specific Test
detox_test({
configuration: "android.emu.debug",
test_name: "e2e/login.test.js"
})
Pattern 3: Fast Iteration
detox_test({
configuration: "ios.sim.debug",
cleanup: false, // Don't uninstall app
reuse: true // Reuse existing installation
})
Appium Workflows
Note: Requires Appium server running (appium command)
Pattern 1: Complete Test Session
// 1. Start session
const sessionResult = await appium_start_session({
platform: "android",
app_path: "/path/to/app.apk",
device_name: "Android Emulator"
})
// Extract session_id from sessionResult
const sessionId = "session-abc123"
// 2. Find email input
const emailResult = await appium_find_element({
session_id: sessionId,
strategy: "accessibility_id",
value: "email-input"
})
// Extract element_id
const emailId = "element-xyz789"
// 3. Input email
await appium_input_text({
session_id: sessionId,
element_id: emailId,
text: "user@example.com"
})
// 4. Find and tap submit button
const submitResult = await appium_find_element({
session_id: sessionId,
strategy: "accessibility_id",
value: "submit-button"
})
const submitId = "element-def456"
await appium_tap({
session_id: sessionId,
element_id: submitId
})
Common Test Scenarios
Scenario 1: Login Flow
Maestro:
- launchApp - tapOn: "Login" - inputText: "user@example.com" - tapOn: "Password" - inputText: "password123" - tapOn: "Submit" - assertVisible: "Home"
React Native TestID Setup:
<TextInput testID="email-input" />
<TextInput testID="password-input" secureTextEntry />
<Button testID="submit-button" onPress={handleLogin} />
Scenario 2: Form Validation
Maestro:
- tapOn: "Submit"
- assertVisible: "Error: Email required"
- tapOn:
id: "email-input"
- inputText: "user@example.com"
- tapOn: "Submit"
- assertNotVisible: "Error"
Scenario 3: Navigation Testing
Maestro:
- launchApp - tapOn: "Profile" - assertVisible: "Profile Screen" - tapOn: "Settings" - assertVisible: "Settings Screen" - back - assertVisible: "Profile Screen"
Scenario 4: List Interaction
Maestro:
- launchApp - assertVisible: "Product List" - tapOn: "iPhone 15" - assertVisible: "Product Details" - tapOn: "Add to Cart" - assertVisible: "Added to Cart"
Debugging Failed Tests
Step 1: View Test Results
get_test_results({
framework: "all",
limit: 10,
response_format: "markdown"
})
Step 2: Analyze Failure
Common failure patterns:
Element not found:
- •Verify testID or text is correct
- •Check if element is rendered on screen
- •Add wait/timeout if needed
Timing issues:
- •Maestro: Built-in synchronization usually handles this
- •Detox: Automatic synchronization
- •Appium: May need explicit waits
Wrong configuration:
- •Verify device is running
- •Check app is installed
- •Confirm framework configuration
Step 3: Iterate
- •Fix the issue in flow file or test code
- •Re-run using appropriate MCP tool
- •Verify success in test results
Best Practices
1. Use TestIDs for Stability
// Good - Stable testID <Button testID="submit-button" title="Submit" /> // Avoid - Text may change <Button title="Submit Form Now" />
2. Keep Flows Focused
# Good - Single responsibility # File: flows/login.yaml - launchApp - tapOn: "Login" - # Login steps only # Avoid - Multiple concerns in one file - launchApp - tapOn: "Login" - # Login + Navigation + Checkout...
3. Organize Test Files
flows/
├── auth/
│ ├── login.yaml
│ ├── signup.yaml
│ └── logout.yaml
├── checkout/
│ ├── add-to-cart.yaml
│ └── complete-order.yaml
└── navigation/
└── main-menu.yaml
4. Use Descriptive Names
# Good - assertVisible: "Welcome, John!" # Avoid - assertVisible: "Text 1"
5. Test Critical Paths First
Priority order:
- •Login/Authentication
- •Core user flows (checkout, booking, etc.)
- •Navigation
- •Edge cases
Framework Comparison
Need help choosing? See frameworks-comparison.md for detailed comparison and recommendations.
Quick Summary:
- •Maestro: Best for AI agents, simplest setup, YAML syntax
- •Detox: Best for React Native performance, JavaScript/TypeScript syntax
- •Appium: Best for multi-framework apps, WebDriver protocol
Helper Scripts
with_device.py - Device Lifecycle Management
Manages emulator/simulator startup, waits for ready, runs command, then cleanup.
# Run tests with device management python scripts/with_device.py --platform android --device "Pixel_7_API_34" -- \ maestro test flows/ # iOS python scripts/with_device.py --platform ios --device "iPhone 15 Pro" -- \ maestro test flows/ # Use existing device (don't start/stop) python scripts/with_device.py --platform android --use-existing -- \ maestro test flows/
generate_flow.py - Flow Template Generator
Generate Maestro YAML flows from templates.
# List available templates python scripts/generate_flow.py --list # Generate login flow python scripts/generate_flow.py login --app-id com.myapp --output flows/login.yaml # Generate form flow python scripts/generate_flow.py form --fields email,password,name --output flows/signup.yaml # Generate navigation flow python scripts/generate_flow.py navigation --screens Home,Profile,Settings --output flows/nav.yaml
run_test_suite.py - Test Suite Runner
Run multiple tests with formatted output and summary.
# Run all flows in directory python scripts/run_test_suite.py flows/ # Run specific flows python scripts/run_test_suite.py flows/login.yaml flows/checkout.yaml # Stop on first failure python scripts/run_test_suite.py flows/ --stop-on-failure # Run with specific device python scripts/run_test_suite.py flows/ --device "iPhone 15 Pro"
capture_screen.py - Screenshot Capture
Capture screenshots from devices during testing.
# Capture from Android python scripts/capture_screen.py --platform android --output screenshots/screen1.png # Capture from iOS python scripts/capture_screen.py --platform ios --device "iPhone 15 Pro" --output screenshots/screen1.png # Auto-generate filename with timestamp python scripts/capture_screen.py --platform android --auto-name --output-dir screenshots/
Example Assets
The assets/ directory contains example flow files you can use as templates:
- •
login-flow.yaml- Login form example - •
navigation-flow.yaml- Screen navigation example
Copy and modify these for your app.
Prerequisites Checklist
Before testing, ensure:
For Maestro:
- • Maestro CLI installed (
curl -Ls https://get.maestro.mobile.dev | bash) - • Android emulator or iOS simulator running
- • App installed on device/simulator
For Detox:
- • Detox CLI installed (
npm install -g detox-cli) - •
.detoxrc.jsconfiguration exists - • App built for testing (
detox build) - • Jest or Mocha configured
For Appium:
- • Appium installed (
npm install -g appium) - • Appium drivers installed (
appium driver install uiautomator2/xcuitest) - • Appium server running (
appium) - • App .apk or .app file available
Troubleshooting
"Command not found" errors:
- •Install the framework using installation commands above
- •Verify framework is in PATH:
which maestro/which detox/which appium
"Device not found" errors:
- •Start emulator/simulator first
- •Use
device_idparameter to specify exact device - •Check available devices:
adb devices(Android) orxcrun simctl list(iOS)
Test timeouts:
- •Increase timeout in flow assertions
- •Check device performance
- •Verify network connectivity for API-dependent tests
Element not found:
- •Use
maestro studioto inspect current screen - •Verify testID or selector is correct
- •Check if element is rendered (may need scroll)