【问题标题】:detox tests not recognising View even after adding id即使在添加 id 后排毒测试也无法识别 View
【发布时间】:2018-12-08 05:32:08
【问题描述】:

如果之前有人问过这个问题,请提前道歉。我遇到了用于 react native 应用程序的 detox e2e 框架,我想尝试一下。

我正在尝试自动化此处给出的演示移动应用程序 - link 由于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)

【问题讨论】:

  • 您能否包含您收到的确切错误消息?
  • @vonovak 请查看编辑。谢谢!
  • 演示应用程序非常老旧,您没有说明您使用的是什么版本的 detox。我首先尝试在 xcode 中使用视觉检查器,以便您查看视图层次结构或升级到 RN 0.55 和最新的 detox。

标签: react-native detox


【解决方案1】:

我查看了该应用程序,并能够让它工作。我在我的 devDependencies 中设置了以下内容。

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

我也添加到 package.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>

然后在e2e/firstTest.spec.js 中我将测试替换为

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

这是我运行detox build &amp;&amp; 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 是否支持可访问性标签,因此如果您希望自动输入文本和点击按钮,可能还有一些工作要做。

为自定义组件添加 testID

见第三步https://github.com/wix/detox/blob/master/docs/Introduction.WritingFirstTest.md

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

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

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

自定义组件

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 在原生视图层次结构中表现为可访问性标识符

【讨论】:

  • 这是一个绝妙的解释。除了自定义组件,我肯定会尝试这个。很好地提出了这个答案。
  • 我今天尝试了这个,但在第一次测试中遇到了同样的错误。我尝试将 jest 和 detox 安装到您拥有的版本,但我无法这样做。是这个原因吗?
  • @demouser123 这令人沮丧。我决定分叉你的 repo 并创建一个包含更改的分支。你可以看到它here。下载我的 fork,切换到分支 detox_testnpm iwatchman watch-del-all,如果已打开 Metro 捆绑器,请关闭它,然后运行 ​​detox build &amp;&amp; detox test。希望这对你有用。
【解决方案2】:

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

【讨论】:

  • 你能否编辑并给出一个简短的例子来说明如何做到这一点。会有帮助的
【解决方案3】:

确实,这个accessibilityLabel 将是您的testID,它将在您的测试工具中被识别:

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

【讨论】:

    猜你喜欢
    • 2014-08-02
    • 2021-06-26
    • 1970-01-01
    • 2021-12-26
    • 2014-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多