【问题标题】:Animated Button block the Detox动画按钮阻止排毒
【发布时间】:2018-05-03 14:43:25
【问题描述】:

这就是我对动画按钮的意思。我让它有一个 ID,但它无法被 Detox 以某种方式定位。

Detox 通过自动将您的测试与应用同步来消除片状问题。如果应用程序繁忙,则测试无法继续到下一行。只有当应用程序空闲时,测试才会恢复。 Detox 非常密切地监控您的应用程序,以便了解它何时处于空闲状态。它跟踪几个异步操作并等待它们完成。这包括:

跟踪当前正在进行的所有网络请求并等待它们完成 跟踪待处理的动画并等待它们完成 跟踪计时器(如 setTimeout)并等待它们到期 跟踪承载异步消息的 React Native 桥接器 跟踪异步 React Native 布局和影子队列 跟踪可能包含未决异步操作的 JavaScript 事件循环

显然有一条线说要跟踪待处理的动画,所以如果按钮保持这样的动画。那么它会一直等待吗?那么,通常如何正确处理这个问题呢?

谢谢

【问题讨论】:

    标签: detox


    【解决方案1】:

    来自排毒文档:

    无尽的循环动画

    默认情况下,排毒会等到动画完成。如果你有一个 无限循环动画,这可能会导致排毒挂起。在这种情况下, 考虑关闭动画同步或移除 使用 react-native-repackager 在您的 E2E 构建中无限循环。

    https://github.com/wix/detox/blob/master/docs/Troubleshooting.Synchronization.md#endless-looping-animations

    一般说明

    无限动画(循环动画)可以让排毒永远等待。 请考虑关闭循环动画进行测试。它也是一个 加速所有动画以进行测试的良好做法。

    https://github.com/wix/detox/blob/master/docs/More.AndroidSupportStatus.md#general-remarks

    Detox 提供disableSynchronization() - 因此您可以暂时禁用同步以解决动画问题 然后在动画消失后重新打开它。然而,这并不适用于所有情况。例如,如果您使用 react-navigation 并且按下按钮将新屏幕推送到导航堆栈,则该按钮仍将继续在后台动画,阻止您计划在新屏幕上运行的任何进一步测试。

    因此,理想情况下,您希望采用其他建议并为您的 E2E 测试禁用这些类型的动画。这里有 3 个可能的选项来实现这一点。

    答:

    Detox 作者建议为此使用react-native-repackager。目前它只支持 RN 0.51,所以这可能并不适合所有人。使用前请查看支持的版本。

    目前仅支持 RN 0.51

    乙:

    设置 React Native 构建环境。根据环境配置变量,您可以在构建 E2E 测试时禁用继续动画。

    https://blog.carbonfive.com/2016/09/29/setting-up-react-native-build-environments-using-nativemodules/

    C:

    我发现最简单的方法是使用react-native-config。这里还有一篇关于 Managing Configuration in React Native 的好文章,带有 react-native-config,以及另一个相关问题 how-to-tell-detox-is-running-tests

    安装包:

    $ yarn add react-native-config

    链接库:

    $ react-native 链接 react-native-config

    为了测试这个解决方案,我在根 React Native 应用程序目录中创建了 2 个文件,.env.production.env.testing。然后我使用 IS_ANIMATE 配置变量来根据构建环境切换动画。您需要将 ENVFILE=.env.testingENVFILE=.env.production 添加到您的 detox 构建配置中。

    .env.production

    ENV_TYPE=Production
    IS_ANIMATE=1
    

    .env.testing

    ENV_TYPE=Testing
    IS_ANIMATE=0
    

    app.js

    import Config from 'react-native-config'
    
    import React, { Component } from 'react'
    import {
      AppRegistry,
      StyleSheet,
      Alert,
      Animated,
      View,
      TouchableOpacity,
      Text
    } from 'react-native'
    
    class example extends Component {
      constructor(props) {
        super(props)
    
        this.state = {
          radius: new Animated.Value(1)
        }
      }
    
      componentDidMount() {
        // only enable animation for production
        if (Config.IS_ANIMATE == true) {
          this.cycleAnimation()
        }
      }
    
      cycleAnimation() {
        Animated.loop(
          Animated.sequence([
            Animated.timing(this.state.radius, {
              toValue: 2,
              duration: 500,
              delay: 1000
            }),
            Animated.timing(this.state.radius, {
              toValue: 1,
              duration: 500
            })
          ])
        ).start()
      }
    
      render() {
        return (
          <View testID='container' style={styles.container}>
            <Text>{Config.ENV_TYPE}</Text>
            <TouchableOpacity
              testID='button'
              onPress={() => Alert.alert("I was pressed")}
            >
              <Animated.View
                style={[
                  styles.button,
                  {transform: [
                    {scale: this.state.radius},
                  ]}
                ]}
              >
                <Text>START DIARY</Text>
              </Animated.View>
            </TouchableOpacity>
          </View>
        )
      }
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center'
      },
      button: {
        justifyContent: 'center',
        alignItems: 'center',
        borderRadius: 60,
        width: 120,
        height: 120,
        backgroundColor: 'green'
      },
      text: {
        padding: 5,
        fontSize: 14
      }
    })
    
    AppRegistry.registerComponent('example', () => example)
    

    example.spec.js

    it('Animated Button', async () => {
      const buttonElement = element(by.id('button'));
      await expect(buttonElement).toBeVisible();
      await buttonElement.tap();
    });
    

    package.json

    "detox": {
      "specs": "e2e",
      "configurations": {
        "ios.sim.release": {
          "binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app",
          "build": "ENVFILE=.env.production export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -project ios/example.xcodeproj -scheme example -configuration Release -sdk iphonesimulator -derivedDataPath ios/build",
          "type": "ios.simulator",
          "name": "iPhone 5s, iOS 10.3"
        },
        "ios.sim.test": {
          "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/example.app",
          "build": "ENVFILE=.env.testing xcodebuild -project ios/example.xcodeproj -scheme example -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build -arch x86_64",
          "type": "ios.simulator",
          "name": "iPhone 5s, iOS 10.3"
        }
      }
    }
    

    发布版本将挂起:detox build --configuration ios.sim.release &amp;&amp; detox test --configuration ios.sim.release

    测试构建将通过:detox build --configuration ios.sim.test &amp;&amp; detox test --configuration ios.sim.test

    【讨论】:

    • 嗨 Antoni4,我试过这种方法,但显然按钮是无休止的动画。当我单击它时,它仍然留在堆栈中,因为我使用了 react_native_navigation。所以屏幕仍然存在,只是不可见。这就是我的假设,即使带有按钮的屏幕不可见,我仍然可以使用层次结构视图看到它,因此它仍然在后台动画?导致同步再次等待的原因是什么?
    • 是的,我明白了,可能是这样。您是否有机会提供一些带有排毒测试的代码示例来重现此问题?
    • 顺便说一下,只是为了测试你的理论。在按下按钮时,您可以在将新屏幕推入堆栈之前禁用按钮动画吗?如果您的理论是正确的,那么 Detox 应该能够继续进行下一个测试。
    • 又想到了一个想法。也许您可以为这种特定的构建类型定义一个环境变量,并在 E2E 测试期间使用它来禁用按钮动画。关于这个主题的好文章:blog.carbonfive.com/2016/09/29/…
    • 或者使用文档中建议的 react-native-repackager 在使用 Detox 执行 E2E 测试时禁用按钮动画。
    【解决方案2】:

    你可以通过使用来解决这个无限的动画循环

    await device.disableSynchronization();
    

    只需在与动画元素交互之前放置这一行 然后你可以再次启用同步

    await device.enableSynchronization();
    

    这个功能之前有一个错误,他们只是在这个版本中修复了它:18.18.0

    【讨论】:

      猜你喜欢
      • 2020-04-29
      • 2020-09-11
      • 1970-01-01
      • 2019-11-21
      • 1970-01-01
      • 2018-12-27
      • 2019-07-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多