How to Debug
Detox Tests
If you need to walk through your Detox tests step by step, add a debugger
statement
inside your test to mark a starting point, e.g.:
describe('Example', () => {
beforeAll(async () => {
await device.launchApp();
+ debugger;
});
Now run Detox with that specific test and --inspect-brk
flag, e.g.:
detox test --inspect-brk -c android.emu.debug e2e/starter.test.js
Assuming you're using Jest, you'll see something like:
DETOX_CONFIGURATION="android.emu.debug" node --inspect-brk ./node_modules/.bin/jest --config e2e/jest.config.js --runInBand e2e/starter.test.js
Debugger listening on ws://127.0.0.1:9229/3dedd03b-8896-4ab8-a0a8-1b647abb9c98
For help, see: https://nodejs.org/en/docs/inspector
To learn more about debugging with --inspect-brk
, refer to
Debugging — Getting Started
on the official Node.js website. This tutorial suggests using Google Chrome for debugging,
but you can also use an IDE to connect to the debugger.
Open Google Chrome
and go to chrome://inspect
tab, where you'll see ./node_modules/.bin/jest
as a remote
target waiting until you click inspect
to attach to it.
Happy debugging!
JavaScript application code
Use debug configurations of your app that rely on React Native Packager running on port 8081 (or another):
ios.sim.debug
android.emu.debug
For the rest of details, please refer to React Native – Debugging.
Native application code
Setting Detox up as a compiling dependency
This step is optional. It is intended for investigating weird crashes or when contributing to Detox itself.
- iOS
- Android
Go to
node_modules/detox
and extractDetox-ios-src.tbz
Drag
Detox-ios-src/Detox.xcodeproj
into your Xcode projectGo to your project settings → General and add Detox.framework to Frameworks, Libraries, and Embedded Content (make sure Embed & Sign is selected under Embed)
Apps should not be submitted to the App Store with the Detox framework linked. Follow this guide only to debug Detox issues in your project. Once finished, make sure to remove Detox.framework from your project.
Add in your Android project settings:
android/settings.gradle+include ':detox'
+project(':detox').projectDir = new File(rootProject.projectDir, '../node_modules/detox/android/detox')In your root build script register
google()
as a repository lookup point in all projects:android/build.gradleallprojects {
repositories {
// ...
+ google()
}
}If
allprojects
section doesn't exist, then add it.In your app’s build script, add to
dependencies
section:android/app/build.gradledependencies {
// ...
+ androidTestImplementation(project(path: ":detox"))
}Stay in that file, just scroll down and add to the
defaultConfig
subsection:android/app/build.gradleandroid {
// ...
defaultConfig {
// ...
+ testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type
+ testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
+ missingDimensionStrategy 'detox', 'full'
}
}
Add a "manual" configuration to your Detox config
- iOS
- Android
{
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "<e.g., iPhone 12 Pro>"
}
}
},
"apps": {
"ios.debug": {
"type": "ios.app",
"binaryPath": "<path to your app binary built before>"
}
},
"configurations": {
"ios.manual": {
"device": "simulator",
"app": "ios.debug",
"behavior": {
"launchApp": "manual"
}
}
}
}
{
"devices": {
"emulator": {
"type": "android.emulator",
"device": {
"avdName": "<e.g., Pixel_API_28>"
}
}
},
"apps": {
"android.debug": {
"type": "android.apk",
"binaryPath": "<path to your app binary built before>"
}
},
"configurations": {
"android.manual": {
"device": "emulator",
"app": "android.debug",
"behavior": {
"launchApp": "manual"
}
}
}
}
While the behavior
section is a mandatory thing to include, there are a few more optional
parameters to disable various side effects and make life easier when debugging:
{
…
"configurations": {
"<your configuration>": {
…
"behavior": {
"launchApp": "manual"
},
+ "session": {
+ "autoStart": true,
+ "debugSynchronization": 0,
+ "server": "ws://localhost:8099",
+ "sessionId": "test"
+ },
+ "testRunner": {
+ "args": {
+ "testTimeout": 999999
+ }
+ }
+ "artifacts": false
},
}
}
Using a preconfigured
session
with an autostarting server removes the legwork of copying and pasting values to the instrumentation runner launch arguments dialog every time before any launch from the IDE. Otherwise, by default when thesession
object omitted,server
andsessionId
are randomly generated for every new test session.The
debugSynchronization: 0
override matters only if you have a globalsession
config withdebugSynchronization
set to a positive integer value. Otherwise, it is not needed. The point is to disable regular app polling requests during debugging, since that only can hinder the debugging.If you are using Jest as a test runner, you might want to prolong the test timeout via forwarding
--testTimeout 999999
to it.Setting
artifacts: false
override also matters only if you have a globalartifacts
config. The motivation is to disable irrelevant taxing activities on the device such as capturing logs screenshots, videos and so on. If your investigation addresses a specific artifact plugin glitch on the native side, then just disable all the non-relevant plugins. See Configuration > Artifacts document for the reference.
Run a specific test
Usually, you would want to focus on a specific test suite to save time, e.g.:
- iOS
- Android
detox test -c ios.manual e2e/someSuite.test.js
detox test -c android.manual e2e/someSuite.test.js
Don't use multiple workers, e.g. -w, --maxWorkers
for Jest, if you set session.sessionId
to a constant value.
Afterwards, you should see your test suite starting as usual until it reaches the app launch, where Detox stops instead and prompts you to launch the app from the IDE:
- iOS
- Android
18:26:07.024 detox[45214] i Waiting for you to manually launch your app in Xcode.
Make sure to pass the launch arguments listed below:
-detoxServer ws://localhost:8099
-detoxSessionId com.wix.detox-example
Press any key to continue...
You’ll need to run your app with the said arguments from Xcode:
Before you launch the app, make sure to put breakpoints at the points of interest, e.g.:
Launch the app with the debugger attached:
The moment you see the app is idle, go back to the Terminal where Detox is running and press any key. If you wish to terminate the process for some reason, use Ctrl+C. In a couple of seconds you are expected to see a confirmation from Detox, e.g.:
Found the app (com.wix.detox-example) with process ID = 16854. Proceeding...
Now the entire test will run as usual until it sends an action to the app, which gets trapped in your breakpoint.
Happy debugging!
18:26:07.024 detox[45214] i Waiting for you to manually launch your app in Android Studio.
Instrumentation class: com.wix.detox.test.test/com.example.DetoxTestAppJUnitRunner
Instrumentation arguments:
------------------------------------
Key | Value
------------------------------------
detoxServer | ws://localhost:8099
detoxSessionId | test
------------------------------------
Press any key to continue...
Now it is time to switch back to Android Studio. You’ll need to run your instrumentation runner with the said arguments,
this is why you should create a debug configuration of Android Instrumented Tests
type similar to the one below:
Make sure to put breakpoints at the points of interest before you start the app.
After the app is launched, go back to the Terminal where Detox is running and press any key. As a result, you are expected to see a confirmation from Detox, e.g.:
Found the app (com.wix.detox-example) with process ID = 16854. Proceeding...
Now the entire test will run as usual until it sends an action to the app, which gets trapped in your breakpoint.
Happy debugging!
Troubleshooting
- iOS
- Android
Here are some known issues you can solve on your own:
DetoxWSClient: Retrying... At connectToServer
I/DetoxWSClient: At connectToServer
D/DetoxWSClient: Retrying...If you see the repeatedly printed messages like above in Android application logs, it's likely that your port is not reversed. Assuming you're following the tutorial and
detoxServer
address isws://localhost:8099
(if not – check what Detox prints you), reverse the port on your device using ADB:adb reverse tcp:8099 tcp:8099
Waited for the new RN-context for too long!
Waited for the new RN-context for too long! (60 seconds)
If you think that’s not long enough, consider applying a custom Detox runtime-config in DetoxTest.runTests().If you see an error like above, you can patch Detox code to disable the timeout here:
detox/android/detox/src/main/java/com/wix/detox/config/DetoxConfig.ktpackage com.wix.detox.config
class DetoxConfig {
@JvmField var idlePolicyConfig: DetoxIdlePolicyConfig = DetoxIdlePolicyConfig()
- @JvmField var rnContextLoadTimeoutSec = 60
+ @JvmField var rnContextLoadTimeoutSec = Int.MAX_VALUE
fun apply() {
idlePolicyConfig.apply()