Skip to main content
Version: 20.x

Project Setup

info

This article mainly covers standard React Native projects. If some steps don't look applicable to your project, please adapt them accordingly, relying on the common sense – look for other file locations, use custom build commands and so on.

If you're using Expo, please refer to the setup guide from their documentation website instead. The setup for Expo projects is different and is not covered in this article.

Step 1: Bootstrap

Out of the box, Detox offers you a first-class integration with Jest, the most popular testing framework for React Native. That's why your first step will be to install or update Jest in your project.

Go to your project's root folder, i.e., where package.json is found, and run:

npm install "jest@^29" --save-dev
Info

The command above will install the latest supported Jest version. The @^29 override is recommended in the first place to prevent you from getting an outdated Jest version unknowingly, under the influence of package lock files. For example, in React Native boilerplate projects, the package-lock.json is apt to restrict npm install jest to installing an older, unsupported version 26.x.

Now it's time to install Detox itself:

npm install detox --save-dev

Now, when all the dependencies are installed, initialize Detox in your project:

detox init

Normally you should see an output like:

Created a file at path: .detoxrc.js
Created a file at path: e2e/jest.config.js
Created a file at path: e2e/starter.test.js
tip

If you see a message like command not found: detox, make sure you have installed Detox command line tools.

After Detox generated these files in your project's root, you still have some work to do with them:

  • .detoxrc.js – Detox config file;
  • e2e/jest.config.js – Jest configuration;
  • e2e/starter.test.js – dummy first test.

Step 2: App configs

In this step you need to provide Detox with the right commands to build your app for iOS and Android, and also the right paths to the app binaries so that Detox can install your app on the device before actually starting the tests.

Open your Detox config and replace YOUR_APP placeholder with the actual app name, e.g.:

.detoxrc.js
   apps: {
'ios.debug': {
type: 'ios.app',
- binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/YOUR_APP.app',
+ binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/example.app',
- build: 'xcodebuild -workspace ios/YOUR_APP.xcworkspace -scheme YOUR_APP -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build'
+ build: 'xcodebuild -workspace ios/example.xcworkspace -scheme example -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build'
},
'ios.release': {
type: 'ios.app',
- binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/YOUR_APP.app',
+ binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/example.app',
- build: 'xcodebuild -workspace ios/YOUR_APP.xcworkspace -scheme YOUR_APP -configuration Release -sdk iphonesimulator -derivedDataPath ios/build'
+ build: 'xcodebuild -workspace ios/example.xcworkspace -scheme example -configuration Release -sdk iphonesimulator -derivedDataPath ios/build'
},
info

If your app uses CocoaPods (all modern React Native projects do since 0.60.0), make sure to run pod install in your ios/ folder before building with Detox.

If your project doesn't use the pods, then you won't have any YourApp.xcworkspace in your iOS project directory. You should search instead for something like YourApp.xcodeproj there, and adjust your build command accordingly:

   apps: {
'ios.debug': {
type: 'ios.app',
binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/example.app',
- build: 'xcodebuild -workspace ios/YOUR_APP.xcworkspace -scheme YOUR_APP -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build'
+ build: 'xcodebuild -project ios/example.xcodeproj -scheme example -sdk -configuration Debug iphonesimulator -derivedDataPath ios/build'
},
'ios.release': {
type: 'ios.app',
binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/example.app',
- build: 'xcodebuild -workspace ios/YOUR_APP.xcworkspace -scheme YOUR_APP -configuration Release -sdk iphonesimulator -derivedDataPath ios/build'
+ build: 'xcodebuild -project ios/example.xcodeproj -scheme example -sdk -configuration Release iphonesimulator -derivedDataPath ios/build'
},

Step 3: Device configs

By default, Detox config suggests default device types for iOS and Android:

.detoxrc.js
/** @type {Detox.DetoxConfig} */
module.exports = {
// ...
devices: {
simulator: {
type: 'ios.simulator',
device: {
type: 'iPhone 12',
},
},
attached: {
type: 'android.attached',
device: {
adbName: '.*', // any attached device
},
},
emulator: {
type: 'android.emulator',
device: {
avdName: 'Pixel_3a_API_30_x86',
},
},
},
};
info

If you plan to use cloud devices instead, check out the Genymotion SaaS guide, which will help you to set up remote Android devices. This tutorial, however, focuses on devices running locally.

Here's how you can check they are correct and change them if you need something else:

To check if a specific Android virtual device (e.g. Pixel_3a_API_30_x86) is installed locally, run:

emulator -list-avds

You should see an output like:

Pixel_3a_API_30_x86
Pixel_API_30
tip

If you see zsh: command not found (or a similar message), please go back to Setting up the environment section where we were redirecting you to the official React Native CLI Quickstart, and make sure you have completed it.

Provided you have ANDROID_SDK_ROOT (or ANDROID_HOME) environment variables defined, using an explicit path to emulator should help:

$ANDROID_SDK_ROOT/emulator/emulator -list-avds

If you don't see that AVD name, you might use another one from the list – just replace it in Detox config, e.g.:

   emulator: {
type: 'android.emulator',
device: {
- avdName: 'Pixel_3a_API_30_x86',
+ avdName: 'Pixel_API_30',
},
},

If the output is completely blank, then you need to open Android Studio and create a new virtual device (AVD) first. Experienced users might do that via avdmanager, if Android Studio is not installed (e.g. on CI).

info

If you wish to use an attached Android device (via USB or wireless network), make sure it is available:

adb devices

If the device is properly connected, you should get an output like this:

List of devices attached
2F6315NVPH device

Assuming the device is available (troubleshooting adb issues is out of scope of this tutorial), you just need to use android.att.* Detox configurations instead of android.emu.* where required.

⚠️ If you have multiple devices connected, replace that loose regular expression (adbName: '.*') in your Detox config with a specific device name.

Step 4: Additional Android configuration

tip

If you want to try out your tests right away on iOS, you can skip to Step 5: Build the app and revisit it when you're ready to move forward with Android.

Assuming you have a regular React Native project, these are the files you normally would need to patch or create if they are missing:

  • Build scripts:
    • android/build.gradle
    • android/app/build.gradle
  • Native test code:
    • android/app/src/androidTest/java/com/<your.package>/DetoxTest.java
  • Manifests:
    • android/app/src/main/AndroidManifest.xml
    • android/app/src/main/res/xml/network_security_config.xml

4.1. Patching build scripts

Open your main build script and apply the suggested changes:

android/build.gradle
 buildscript {
ext {
buildToolsVersion = "31.0.0"
minSdkVersion = 21 // (1)
compileSdkVersion = 30
targetSdkVersion = 30
+ kotlinVersion = 'X.Y.Z' // (2)
}

dependencies {
classpath("com.android.tools.build:gradle:7.1.1")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("de.undercouch:gradle-download-task:5.0.1")
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") // (3)


allprojects {
repositories {

google()
+ maven { // (4)
+ url("$rootDir/../node_modules/detox/Detox-android")
+ }
maven { url 'https://www.jitpack.io' }
}

Here is the explanation of those changes, numbered 1-4:

  1. Make sure your minSdkVersion is at least 18 or higher.
  2. We recommend you to define a global kotlinVersion constant you would use in the next step. Replace X.Y.Z with the actual version number. To get one, open Android Studio, go to Preferences > Languages & Frameworks > Kotlin and look at Current Kotlin plugin version field. For example, 211-1.5.30-release-408-AS7442.40 means you have version 1.5.30.
  3. The line adds Kotlin Gradle plugin to the build script. If your project is not entirely new, there's a chance you might have it already, so make sure you aren't adding it twice. 😉
  4. Last, we add Detox as a precompiled native dependency, .aar. If you need to have Detox as a compiling dependency instead, consult the respective section in Debugging guide.

Now let's move on to the next build script and prepare it:

android/app/build.gradle
 

android {

defaultConfig {

versionCode 1
versionName "1.0"
+ testBuildType System.getProperty('testBuildType', 'debug')
+ testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'

buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro"

signingConfig signingConfigs.release
}
}


dependencies {
+ androidTestImplementation('com.wix:detox:+')
+ implementation 'androidx.appcompat:appcompat:1.1.0'
implementation fileTree(dir: "libs", include: ["*.jar"])
ProGuard notice

Detox relies on Android Reflection API to integrate with React Native on Android, that's why you have to exempt some of its native code from ProGuard minification. Otherwise, you'll see Detox crashing or hanging up infinitely upon an attempt to run tests with your app built in release mode.

4.2. Adding an auxiliary Android test

Detox requires that your project has a single dummy native Android test with some special content, which will be picked up by testRunner that you just added in the previous step, so let's create it now.

Copy the snippet below to create a file under the following path (where <your.package> is your actual package name):

android/app/src/androidTest/java/com/<your.package>/DetoxTest.java
package com.<your.package>; // (1)

import com.wix.detox.Detox;
import com.wix.detox.config.DetoxConfig;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;

@RunWith(AndroidJUnit4.class)
@LargeTest
public class DetoxTest {
@Rule // (2)
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false);

@Test
public void runDetoxTests() {
DetoxConfig detoxConfig = new DetoxConfig();
detoxConfig.idlePolicyConfig.masterTimeoutSec = 90;
detoxConfig.idlePolicyConfig.idleResourceTimeoutSec = 60;
detoxConfig.rnContextLoadTimeoutSec = (BuildConfig.DEBUG ? 180 : 60);

Detox.runTests(mActivityRule, detoxConfig);
}
}

You can see there are two lines (1 and 18) that require extra care:

  1. Replace with your package name. To look it up, you could copy and paste the first line from android/app/src/main/java/com/<your.package>/MainActivity.java.
  2. Usually not the case, but you might have a custom activity name instead of a default MainActivity. To check whether it is so or not, open your android/app/src/main/AndroidManifest.xml, and check what your main activity is called:

<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="standard"

4.3. Enabling unencrypted traffic for Detox

info

For Detox to work, its native code running on Android device has to be able to connect to the Node.js host running tests. It sends an unencrypted HTTP traffic via virtual localhost interface, that's why you need to create a new file which adds a couple of exceptions to the security rules.

If properly configured, this approach in no way compromises the security settings of your app. For more details, refer to Android’s security-config guide and the dedicated article in the Android developers blog.

Create a new network security config file for Android (or patch it if you have one):

android/app/src/main/res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.0.2.2</domain>
<domain includeSubdomains="true">localhost</domain>
</domain-config>
</network-security-config>

If you had no network security config before, it means you also have to register it after creation:

android/app/src/main/AndroidManifest.xml
 <manifest>
<application

+ android:networkSecurityConfig="@xml/network_security_config">
</application>
</manifest>

🏆 Pat yourself on the back! The hardest part is over, now your Android app is ready to be used with Detox.

Step 5: Build the app

detox build --configuration ios.sim.debug
tip

If the build is failing, try out our Troubleshooting section.

Note that Detox CLI just executes the build command you specified in your Detox config (.detoxrc.js) for a specific configuration. In the other words, it has no extra logic – it just takes the command and runs it, nothing more and nothing less.

Once your build is ready to use, please proceed to the next article.