AgentSkillsCN

rn-testing

利用 Maestro、Detox 和 Appium,为 React Native 移动应用提供自动化测试支持。当您需要测试 React Native 应用、编写移动测试流程、运行 UI 测试、调试移动应用故障,或自动化移动测试工作流时,此技能将助您事半功倍。同时支持 iOS 与 Android 两大平台。

SKILL.md
--- frontmatter
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 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

code
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)

bash
python scripts/generate_flow.py login --app-id com.myapp --output flows/login.yaml

Option B: Write manually

Save as flows/login.yaml:

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:

jsx
<Button testID="login-button" title="Login" />

Then reference in Maestro:

yaml
- tapOn:
    id: "login-button"

2. Run the Flow

Option A: With device management (recommended)

bash
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)

typescript
maestro_run_flow({
  flow_file: "flows/login.yaml",
  response_format: "markdown"
})

3. View Results

typescript
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)

bash
# 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:

typescript
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

bash
# Run suite with formatted output
python scripts/run_test_suite.py flows/ --stop-on-failure

Or use MCP tools:

typescript
maestro_test({
  flow_paths: [
    "flows/login.yaml",
    "flows/navigation.yaml",
    "flows/checkout.yaml"
  ]
})

Pattern 3: Continuous Development

Use when: Developing tests iteratively

typescript
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

typescript
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.js configuration file in project
  • App built for testing: detox build --configuration ios.sim.debug

Pattern 1: Run All Tests

typescript
detox_test({
  configuration: "ios.sim.debug"
})

Pattern 2: Run Specific Test

typescript
detox_test({
  configuration: "android.emu.debug",
  test_name: "e2e/login.test.js"
})

Pattern 3: Fast Iteration

typescript
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

typescript
// 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:

yaml
- launchApp
- tapOn: "Login"
- inputText: "user@example.com"
- tapOn: "Password"
- inputText: "password123"
- tapOn: "Submit"
- assertVisible: "Home"

React Native TestID Setup:

jsx
<TextInput testID="email-input" />
<TextInput testID="password-input" secureTextEntry />
<Button testID="submit-button" onPress={handleLogin} />

Scenario 2: Form Validation

Maestro:

yaml
- tapOn: "Submit"
- assertVisible: "Error: Email required"
- tapOn:
    id: "email-input"
- inputText: "user@example.com"
- tapOn: "Submit"
- assertNotVisible: "Error"

Scenario 3: Navigation Testing

Maestro:

yaml
- launchApp
- tapOn: "Profile"
- assertVisible: "Profile Screen"
- tapOn: "Settings"
- assertVisible: "Settings Screen"
- back
- assertVisible: "Profile Screen"

Scenario 4: List Interaction

Maestro:

yaml
- 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

typescript
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

  1. Fix the issue in flow file or test code
  2. Re-run using appropriate MCP tool
  3. Verify success in test results

Best Practices

1. Use TestIDs for Stability

jsx
// Good - Stable testID
<Button testID="submit-button" title="Submit" />

// Avoid - Text may change
<Button title="Submit Form Now" />

2. Keep Flows Focused

yaml
# 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

code
flows/
├── auth/
│   ├── login.yaml
│   ├── signup.yaml
│   └── logout.yaml
├── checkout/
│   ├── add-to-cart.yaml
│   └── complete-order.yaml
└── navigation/
    └── main-menu.yaml

4. Use Descriptive Names

yaml
# Good
- assertVisible: "Welcome, John!"

# Avoid
- assertVisible: "Text 1"

5. Test Critical Paths First

Priority order:

  1. Login/Authentication
  2. Core user flows (checkout, booking, etc.)
  3. Navigation
  4. 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.

bash
# 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.

bash
# 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.

bash
# 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.

bash
# 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.js configuration 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_id parameter to specify exact device
  • Check available devices: adb devices (Android) or xcrun 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 studio to inspect current screen
  • Verify testID or selector is correct
  • Check if element is rendered (may need scroll)

Additional Resources