rn-testing
Automated testing for React Native mobile applications using Maestro, Detox, and Appium. Use this skill when testing React Native apps, writing mobile test flows, running UI tests, debugging mobile app failures, or automating mobile testing workflows. Supports iOS and Android platforms.
SKILL.md
| Name | rn-testing |
| Description | Automated testing for React Native mobile applications using Maestro, Detox, and Appium. Use this skill when testing React Native apps, writing mobile test flows, running UI tests, debugging mobile app failures, or automating mobile testing workflows. Supports iOS and Android platforms. |
name: rn-testing description: Automated testing for React Native mobile applications using Maestro, Detox, and Appium. Use this skill when testing React Native apps, writing mobile test flows, running UI tests, debugging mobile app failures, or automating mobile testing workflows. Supports iOS and Android platforms.
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 testingdetox_test- Gray-box React Native testingappium_start_session/appium_find_element/appium_tap/appium_input_text- Cross-platform WebDriver automationget_test_results- View test execution history
Helper Scripts Available:
scripts/with_device.py- Manage device/emulator lifecyclescripts/generate_flow.py- Generate Maestro YAML flows from templatesscripts/run_test_suite.py- Run multiple tests with formatted outputscripts/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 examplenavigation-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)