mcpField
D
detox-skill

detox-skill

github.com/lambdatestテスト・品質384243 回インストール2 週間前に更新
リポジトリ

detox-skill について

React NativeアプリをテストするQAエンジニア向けのDetoxガイドです。要素の照合、操作、アサーション、デバイス制御に加え、AndroidとiOSのテストをローカルまたはTestMu AIクラウドで実行する方法を説明します。

主な機能

  1. 01Detoxのテスト導入と設定
  2. 02要素マッチャーとアサーション
  3. 03UI操作とデバイス制御
  4. 04AndroidとiOSのテストコマンド
  5. 05TestMu AIクラウド実行ガイド
  6. 06アンチパターンと応用資料

活用シーン

  1. 01React NativeのUIテスト作成
  2. 02要素の表示状態とテキストの確認
  3. 03デバイス状態の操作とジェスチャーの実行
  4. 04クラウド実行用モバイルテスト成果物の準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/lambdatest/agent-skills --skill detox-skill

インストール後、Claude Code で/detox-skillを入力して読み込まれたか確認します。

同梱ファイルreference/advanced-patterns.mdreference/playbook.md

詳細

Detox 自動化スキル

Detox を専門とするシニア React Native QA エンジニアです。

基本パターン

基本的なテスト
describe('Login', () => {
  beforeAll(async () => {
    await device.launchApp();
  });

  beforeEach(async () => {
    await device.reloadReactNative();
  });

  it('should login with valid credentials', async () => {
    await element(by.id('emailInput')).typeText('[email protected]');
    await element(by.id('passwordInput')).typeText('password123');
    await element(by.id('loginButton')).tap();
    await expect(element(by.id('dashboardTitle'))).toBeVisible();
    await expect(element(by.text('Welcome'))).toBeVisible();
  });

  it('should show error for invalid credentials', async () => {
    await element(by.id('emailInput')).typeText('[email protected]');
    await element(by.id('passwordInput')).typeText('wrong');
    await element(by.id('loginButton')).tap();
    await expect(element(by.id('errorMessage'))).toBeVisible();
  });
});
マッチャー(要素の検索)
element(by.id('uniqueId'))                    // testID prop (best)
element(by.text('Login'))                      // Text content
element(by.label('Submit'))                    // Accessibility label
element(by.type('RCTTextInput'))              // Native type
element(by.traits(['button']))                 // iOS traits

// Combined
element(by.id('list').withDescendant(by.text('Item 1')))
element(by.id('item').withAncestor(by.id('list')))

// At index (multiple matches)
element(by.text('Delete')).atIndex(0)
アクション
await element(by.id('btn')).tap();
await element(by.id('btn')).longPress();
await element(by.id('btn')).multiTap(3);
await element(by.id('input')).typeText('hello');
await element(by.id('input')).replaceText('new text');
await element(by.id('input')).clearText();
await element(by.id('scrollView')).scroll(200, 'down');
await element(by.id('scrollView')).scrollTo('bottom');
await element(by.id('item')).swipe('left', 'fast');
await element(by.id('input')).tapReturnKey();
アサーション
await expect(element(by.id('title'))).toBeVisible();
await expect(element(by.id('title'))).not.toBeVisible();
await expect(element(by.id('title'))).toExist();
await expect(element(by.id('title'))).toHaveText('Welcome');
await expect(element(by.id('toggle'))).toHaveToggleValue(true);
await expect(element(by.id('input'))).toHaveValue('hello');
デバイス制御
await device.launchApp({ newInstance: true });
await device.reloadReactNative();
await device.sendToHome();
await device.terminateApp();
await device.installApp();
await device.shake();                       // Shake gesture
await device.setLocation(37.7749, -122.4194); // GPS
await device.setURLBlacklist(['.*cdn.example.*']); // Block URLs
アンチパターン
悪い例良い例理由
あらゆる場所でwaitFor().withTimeout()を使うDetox の自動同期を信頼するDetox は自動的に待機します
コンポーネントにtestIDがないtestIDプロパティを追加する安定したセレクターを使用できます
すべてのテストでdevice.launchApp()を使うdevice.reloadReactNative()を使うより高速です
手動で遅延を入れるDetox の同期機能を使う待機機能が組み込まれています
.detoxrc.js の設定
module.exports = {
  testRunner: { args: { config: 'e2e/jest.config.js' } },
  apps: {
    'ios.debug': {
      type: 'ios.app',
      binaryPath: 'ios/build/MyApp.app',
      build: 'xcodebuild -workspace ios/MyApp.xcworkspace -scheme MyApp -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build',
    },
    'android.debug': {
      type: 'android.apk',
      binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk',
      build: 'cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug',
      reversePorts: [8081],
    },
  },
  devices: {
    simulator: { type: 'ios.simulator', device: { type: 'iPhone 16' } },
    emulator: { type: 'android.emulator', device: { avdName: 'Pixel_7_API_34' } },
  },
  configurations: {
    'ios.sim.debug': { device: 'simulator', app: 'ios.debug' },
    'android.emu.debug': { device: 'emulator', app: 'android.debug' },
  },
};

TestMu AI でのクラウド実行

Detox はネイティブのテストランナー(Android 用の Espresso、iOS 用の XCUITest)を生成します。ビルド済みアーティファクトをアップロードし、フレームワークビルドを実行して、TestMu AI クラウドで実行します。

Android(Espresso)のクラウド実行
# 1. Build the app and test APKs
detox build --configuration android.emu.debug

# 2. Upload app APK
curl -u "$LT_USERNAME:$LT_ACCESS_KEY" \
  -X POST "https://manual-api.lambdatest.com/app/upload/realDevice" \
  -F "appFile=@android/app/build/outputs/apk/debug/app-debug.apk" \
  -F "name=DetoxApp"
# Response: {"app_url": "lt://APP_ID", ...}

# 3. Upload test APK
curl -u "$LT_USERNAME:$LT_ACCESS_KEY" \
  -X POST "https://manual-api.lambdatest.com/app/upload/realDevice" \
  -F "appFile=@android/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk" \
  -F "name=DetoxTestSuite"
# Response: {"app_url": "lt://TEST_SUITE_ID", ...}

# 4. Trigger Espresso build
curl -X POST "https://mobile-api.lambdatest.com/framework/v1/espresso/build" \
  -H "Authorization: Basic <BASE64_AUTH>" \
  -H "Content-Type: application/json" \
  -d '{
    "app": "lt://APP_ID",
    "testSuite": "lt://TEST_SUITE_ID",
    "device": ["Galaxy S21 5G-12", "Pixel 6-12"],
    "build": "Detox-Android",
    "deviceLog": true,
    "video": true
  }'
iOS(XCUITest)のクラウド実行
# 1. Build the iOS app and test runner
detox build --configuration ios.sim.release

# 2. Create .ipa from the build artifacts, then upload
curl -u "$LT_USERNAME:$LT_ACCESS_KEY" \
  -X POST "https://manual-api.lambdatest.com/app/upload/realDevice" \
  -F "[email protected]" -F "name=DetoxApp"

# 3. Upload test runner .ipa
curl -u "$LT_USERNAME:$LT_ACCESS_KEY" \
  -X POST "https://manual-api.lambdatest.com/app/upload/realDevice" \
  -F "[email protected]" -F "name=DetoxTestSuite"

# 4. Trigger XCUITest build
curl -X POST "https://mobile-api.lambdatest.com/framework/v1/xcui/build" \
  -H "Authorization: Basic <BASE64_AUTH>" \
  -H "Content-Type: application/json" \
  -d '{
    "app": "lt://APP_ID",
    "testSuite": "lt://TEST_SUITE_ID",
    "device": ["iPhone 14-16", "iPhone 13-15"],
    "build": "Detox-iOS",
    "devicelog": true,
    "video": true
  }'

クイックリファレンス

タスクコマンド
iOS をビルドdetox build --configuration ios.sim.debug
iOS のテストdetox test --configuration ios.sim.debug
Android をビルドdetox build --configuration android.emu.debug
Android のテストdetox test --configuration android.emu.debug
特定のテストdetox test --configuration ios.sim.debug e2e/login.test.js
動画を録画detox test --record-videos all
スクリーンショットを撮影await device.takeScreenshot('login-page')

セットアップ

npm install detox --save-dev
npm install jest jest-circus --save-dev
detox init

React Native コンポーネントのセットアップ

// Add testID to components for Detox
<TextInput testID="emailInput" placeholder="Email" />
<TextInput testID="passwordInput" placeholder="Password" secureTextEntry />
<Button testID="loginButton" title="Login" onPress={handleLogin} />
<Text testID="errorMessage">{error}</Text>

発展的なパターン

発展的なパターン、デバッグガイド、CI/CD 連携、ベストプラクティスについては、 reference/playbook.mdを参照してください。

コメント