15

问题

我们有一个相当复杂的应用程序,我们不希望在每个测试用例中都经历整个过程以到达特定的屏幕来测试它,或者我们只想跳转到特定的一个,其中一些状态存储在 redux 存储中。


我试过的

我做了多个加载特定屏幕的初始状态,所以我可以直接测试它,并且对于每次运行排毒测试我加载不同的 mocha.opts 来选择这部分测试用例并使用'react-native-config'所以我可以在每次运行中加载不同的状态,例如,为了加载屏幕,我将执行以下操作:

  1. 为具有我当前正在测试的屏幕的所有详细信息的 redux 商店创建 initialState。
  2. 通过在其中指定 -f 标志创建 mocha.opts 以仅运行此测试用例。
  3. 创建 .env.test.screenX 文件,它将告诉商店根据我选择的 ENVFILE 加载哪个初始状态。
  4. 为 detox 中的每个屏幕创建不同的配置,以便它可以通过 detox CLI 加载正确的 mocha opts。
  5. 每次我运行命令 ENVFILE=env.test.screenX react-native run-ios 所以项目将使用此配置构建,然后我可以运行 detox test -c 。

问题

我的方法非常复杂,需要大量设置和开销来为每个屏幕运行测试,所以我想知道是否有人有同样的问题,我该如何解决?一般来说,我该如何处理 detox 中的 react native 线程?

4

2 回答 2

8

我认为 detox 无法在运行时与反应本机线程进行通信并更改状态,所以我想到了一个使用模拟技术的小技巧,正如Leo Natan提到的那样,它可能对你的情况有用

您可以使用屏幕 (App.e2e.js) 模拟您的 App.js 文件,该屏幕具有一些具有已知 testID 的按钮每个按钮调度加载特定状态以存储所需的所有操作,您可以通过按以下之一启动每个测试套件方法中的按钮,beforeEach然后您可以开始正常的测试流程

例如:

如果您想测试一个很远的屏幕(当用户实际使用应用程序时需要点击太多次才能到达)并且需要身份验证,您可以具有以下结构:

App.e2e.js 有 2 个按钮:

  • 一个用于身份验证的调度动作,如onAuthenticationSuccess(user, authToken)
  • 另一个用于导航到该屏幕this.navigation.navigate("screenName")

测试.js

describe("Screen work as intended", () => {
  beforeEach(async () => {
    await device.reloadReactNative();
    await element(by.id("authButtonID")).tap();
    await element(by.id("navigateButtonID")).tap();
  });

  it("should do something", async () => {
    //user is loaded in store
    //current screen is the screen you want to test
  });
});
于 2018-03-28T07:03:00.380 回答
0

If you are using Expo and it's release-channels for specifying the environment, here is what you could do:

  1. Create a method resetStorage like suggested here: How to reset the state of a Redux store? (which you could have already implemented in logout)
  2. In App.js import resetStorage method
  3. In App.js add: import { Constants } from 'expo'
  4. Then add a button with testID="resetStorageBtn" to your render method which you can use for testing purposes and which won't be visible in production release-channel. So render might look similar to this:

    return (
      <Root>
        {Constants.manifest.releaseChannel !== 'production' &&
            (<View>
              <Button onPress={() => resetStorage()} testID="resetStorageBtn">
                <Text>Reset storage</Text>
              </Button>
            </View>
          )}
        <View>
          <AppNavigator />
        </View>
      </Root>
    );
    
于 2019-02-05T19:42:12.643 回答