How to tell Detox is running tests?

老子叫甜甜 提交于 2019-12-05 02:40:11

Try using react-native-config. Here is also a good article on Managing Configuration in React Native with react-native-config.

I also gave an answer here animated-button-block-the-detox with working example of how react-native-config can be used to disable looping animations during testing.

The basic idea is that you create .env config files for all your different build environments (development, production, test, etc). These hold your configuration variables that you can access from either Javascript, Objective-C/Swift, or Java.

You then specify which .env config file to use when building your app:

$ ENVFILE=.env.staging react-native run-ios # bash

And this is an example of package.json file where detox uses .env config files for building the app.

"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"
    }
  }
}

We are taking advantage of the fact detox invokes your binary with --args -detoxServer ... -detoxSessionId ... on the iOS command line and { detoxServer: ..., detoxSessionId: ... } set in InstrumentationRegistry in android.

The way we are currently exposing this to JS is a bit much for a StackOverflow answer, but here's some sample code that along with react native's docs should get you there - for Android:

// This will throw ClassNotFoundException if not running under any test,
// but it still might not be running under Detox
Class<?> instrumentationRegistry = Class.forName("android.support.test.InstrumentationRegistry");
Method getArguments = instrumentationRegistry.getMethod("getArguments");
Bundle argumentsBundle = (Bundle) getArguments.invoke(null);

// Say you're in your BaseJavaModule.getConstants() implementation:
return Collections.<String, Object>singletonMap("isDetox", null != argumentsBundle.getString("detoxServer"));

And on iOS, something like (don't have an Objective-C compiler ATM):

return @{@"isDetox": [[[NSProcessInfo processInfo] arguments] containsObject: @"-detoxServer"]}

Note it's also possible to get detox to add your own arguments with:

detox.init(config, { launchApp: false });
device.launchApp({ newInstance: true, launchArgs: {
  myCustomArg: value,
  ...,
} });

It would be great to get this polished up to a module at some point.

Tests/production code that has knowledge of the environment is messy IMO.
The way I recommend doing it is by creating different app flavour for testing.

If you use React Native, check out react-native-repackager's instructions. Alternatively, Detox docs have that section as well. If you write Java code for Android, use gradle build flavours to create a flavours for testing.

You can find more on how we mock in our E2E suites here.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!