排毒测试即使在添加 id 后也无法识别视图



如果之前有人问过,请提前道歉。我遇到了用于 react 本机应用程序的detoxe2e 框架,我想尝试一下。

我正在尝试自动化此处给出的演示移动应用程序 - 链接 由于detox中的测试使用testID作为定位器之一,所以我在app/screen/LoginScreenMaterial.js内部的LoginScreenMaterial.js文件中添加一个定位器,如下所示

<View testID="login_screen" style={{width: this._width, justifyContent: 'center'}}>
<RkCard style={styles.container}>
<View rkCardHeader style={styles.header}>
<RkText/>
<RkText style={styles.label}>Sign in into your account</RkText>
</View>

但是,即使在成功构建应用程序之后,我也使用这个简单的测试运行了该应用程序

it('should have welcome screen', async () => {
await expect(element(by.id('login_screen'))).toBeVisible();
});

但是,测试仍然失败,无法识别元素。在这个测试中,我错过了什么?我们能不能在.js文件中明确添加这样的testID

编辑 1:添加错误消息

1) Example
should have welcome screen:
Error: Error: Cannot find UI Element.
Exception with Assertion: {
"Assertion Criteria" : "assertWithMatcher:matcherForSufficientlyVisible(>=0.750000)",
"Element Matcher" : "(((respondsToSelector(accessibilityIdentifier) && accessibilityID('login_screen')) && !(kindOfClass('RCTScrollView'))) || (kindOfClass('UIScrollView') && ((kindOfClass('UIView') || respondsToSelector(accessibilityContainer)) && ancestorThatMatches(((respondsToSelector(accessibilityIdentifier) && accessibilityID('login_screen')) && kindOfClass('RCTScrollView'))))))",
"Recovery Suggestion" : "Check if the element exists in the UI hierarchy printed below. If it exists, adjust the matcher so that it accurately matches element."
}
Error Trace: [
{
"Description" : "Interaction cannot continue because the desired element was not found.",
"Error Domain" : "com.google.earlgrey.ElementInteractionErrorDomain",
"Error Code" : "0",
"File Name" : "GREYElementInteraction.m",
"Function Name" : "-[GREYElementInteraction matchedElementsWithTimeout:error:]",
"Line" : "124"
}
]
at Client.execute (node_modules/detox/src/client/Client.js:74:13)

我看了一下应用程序,并能够让它工作。我在我的开发依赖项中设置了以下内容。

"devDependencies": {
...
"jest": "23.2.0",
"detox": "8.0.0"
...
},

到包.json我还添加了

"detox": {
"configurations": {
"ios.sim.debug": {
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/BoomApp.app",
"build": "xcodebuild -project ios/BoomApp.xcodeproj -scheme BoomApp -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
"type": "ios.simulator",
"name": "iPhone 7"
}
},

我跑detox init -r jest

然后,我能够让它识别出何时渲染了特定屏幕,我通过将testID添加到ScrollView LoginScreenBlur中来做到这一点.js(第23行(

<AppWrapper>
<ScrollView contentContainerStyle={{flex: 1}} testID={'login_screen'}>
....
</ScrollView>
</AppWrapper>

A 然后在e2e/firstTest.spec.js我用

it('should have loginScreen', async () => {
await expect(element(by.id('login_screen'))).toBeVisible();
});

这是我运行detox build && detox test后的控制台响应

node_modules/.bin/jest e2e --config=e2e/config.json --maxWorkers=1 --testNamePattern='^((?!:android:).)*$'
server listening on localhost:64579...
: Searching for device matching iPhone 7...
: Uninstalling org.reactjs.native.example.BoomApp...
: org.reactjs.native.example.BoomApp uninstalled
: Installing /Users/work/Downloads/react-native-ui-kitten-demo-app-master/ios/build/Build/Products/Debug-iphonesimulator/BoomApp.app...
: /Users/work/Downloads/react-native-ui-kitten-demo-app-master/ios/build/Build/Products/Debug-iphonesimulator/BoomApp.app installed
: Terminating org.reactjs.native.example.BoomApp...
: org.reactjs.native.example.BoomApp terminated
: Launching org.reactjs.native.example.BoomApp...
7: org.reactjs.native.example.BoomApp launched. The stdout and stderr logs were recreated, you can watch them with:
tail -F /Users/work/Library/Developer/CoreSimulator/Devices/AF406169-5CF3-4480-9D00-8F934C420043/data/tmp/detox.last_launch_app_log.{out,err}
PASS  e2e/firstTest.spec.js (7.935s)
Example
✓ should have loginScreen (1499ms)
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        8.87s, estimated 9s
Ran all test suites matching /e2e/i with tests matching "^((?!:android:).)*$".

该应用程序似乎默认启动LoginScreenBlur,因此首先测试它而不是LoginScreenMaterial是有意义的。

我注意到的一件事是应用程序使用RKTextInputRkButton,这些不是本机组件,而是本机组件的包装器。这意味着您需要将 testID 向下传递到您希望拥有 testID 的本机组件。我不确定react-native-ui-kitten是否支持辅助功能标签,因此如果您希望自动输入文本和点击按钮,可能还需要做更多工作。

将测试ID 添加到自定义组件

请参阅步骤 3 https://github.com/wix/detox/blob/master/docs/Introduction.WritingFirstTest.md

请注意,并非所有 React 组件都支持此属性。React Native 中的大多数内置原生组件,如 View、Text、TextInput、Switch、ScrollView 都支持。如果您创建自己的复合组件,则必须手动将此 prop 传播到正确的本机组件。

此处提供了将 testID 添加到自定义组件的更详细说明 https://github.com/wix/detox/blob/master/docs/Troubleshooting.RunningTests.md#cant-find-my-component-even-though-i-added-testid-to-its-props

简而言之,您应该按如下方式实现自定义组件。

自定义组件

export class MyCompositeComponent extends Component {
render() {
return (
<TouchableOpacity testID={this.props.testID}>
<View>
<Text>Something something</Text>
</View>
</TouchableOpacity>
);
}
}

使用自定义组件

然后你应该像这样使用它。

render() {
return <MyCompositeComponent testID='MyUniqueId123' />;
}

搜索层次结构

如果您已完成上述操作,并且确定您的项目具有正确的 testID 并且测试仍然失败,则可以在视图层次结构中搜索它 https://github.com/wix/detox/blob/master/docs/Troubleshooting.RunningTests.md#debug-view-hierarchy

我不会完整重复上述帖子,但步骤是

  1. 在模拟器中启动可调试的应用(不是发布版本(
  2. 打开 Xcode
  3. 将 Xcode 附加到应用进程
  4. 按"调试视图层次结构"按钮
  5. 这将打开层次结构查看器,并显示应用的本机视图层次结构的细分。在这里,您可以浏览视图
  6. React Native testID 在原生视图层次结构中表现为可访问性标识符

使用 AccessiblityLabel 将 ID 添加到视图元素: https://facebook.github.io/react-native/docs/accessibility.html

事实上,这个可访问性标签将成为你的testID,它将在你的测试工具中被识别:

<TouchableOpacity
accessible={true}
accessibilityLabel={'Tap me!'}
onPress={this._onPress}>
<View style={styles.button}>
<Text style={styles.buttonText}>Press me!</Text>
</View>
</TouchableOpacity>

最新更新