关于 detox-skill
面向 React Native 应用 QA 测试的 Detox 技能指南,介绍元素匹配、操作、断言和设备控制。还涵盖 Android 与 iOS 测试命令,以及在本地或 TestMu AI 云端运行测试的流程。
主要功能
- 01Detox 测试安装与配置
- 02元素匹配器与断言
- 03界面操作与设备控制
- 04Android 和 iOS 测试命令
- 05TestMu AI 云端执行指南
- 06反模式与进阶参考
适用场景
- 01编写 React Native 界面测试
- 02检查元素可见性与文本
- 03执行设备状态操作和手势
- 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。
评论
支持 Markdown