Detox: Superfast E2E React Native UI Testing

  Mai 27, 2019

In recent years, React Native has become a very popular technology in the race of cross-platform mobile application development but choosing a UI testing tool for React Native apps might be quite tricky. There are two great UI testing frameworks for React Native apps – Appium and Detox. Appium is widely used for UI testing but Detox is a grey-box, faster and easy to learn tool for the UI testing of React Native apps. In this tutorial, we will set up some Detox tests for a simple, new React Native app.

Detox: End-to-End Mobile UI Testing

As you may have known, the major problems in the mobile UI testing are slowness and flakiness. The tools like Appium are completely black-box and uses client-server architecture which causes flakiness in the UI tests. Detox is designed to solve the problem of slowness and flakiness for mobile UI testing. Some of Detox’s great features are as follows

  • Detox monitors the asynchronous operations in the app to reduce the flakiness of finding the async elements in the app UI.
  • Detox is a grey-box testing tool so it can access the code and data from your mobile apps. It’s an in-process tool and doesn’t use client-server architecture for test execution so it’s way faster than Appium or other third-party mobile test automation frameworks.
  • Detox is easy to be connected to any CI systems and popular cloud testing services.
  • Detox is awesome for fast feedback on your E2E testing which doesn’t need the connection to real devices.
  • React Native developers would love Detox as it’s faster, debuggable and can be used with any test runner like Jest or Mocha.

Detox currently has limited support for iOS real device testing but if your app doesn’t have hardware interface then you can easily skip that part to compensate on faster and less flaky UI testing.

Setting Up Detox for E2E Testing

The process of setting up Detox for your existing React Native app would be fairly simple. If you are already running your React Native apps, the basic requirements for running iOS and Android app in the simulator must be fulfilled.  In this tutorial, we will focus on iOS but Android-specific setup would be fairly easy once you get on with iOS. As a pre-requisite, you need a macOS with Xcode installed on it. You also need to install Node and Homebrew to download the packages required for running React Native apps. To recap, you will need the following

As part of this tutorial, we will create a simple, new React Native app, HelloDetox and enable UI testing support using Detox.

Create React Native App

React Native has great documentation to get started with the basic app. We can easily create a sample app by installing a few dependencies from macOS. We need a node and watchman package, to get going with React Native. You can easily install those packages with Homebrew.

$ brew install node
$ brew install watchman

Once you get the node installed, you should be able to access the ‘npm’ commands from the terminal. Now you can install React Native globally and create our first HelloDetox app.

$ npm install -g react-native-cli
$ react-native init HelloDetox

At this point, React Native will generate the boilerplate code for building both Android and iOS apps. You can run the app inside the Android emulator or iOS simulator if you got any simulator open.

Let’s run the app inside the iOS simulator using the following command

$ cd HelloDetox
$ react-native run-ios

Alternatively, you can launch the Metro Bundler in the background and run the app from Xcode. Now we can edit app.js file to display the content on the screen. The React Native tutorial provides lots of examples. For the purpose of this tutorial, let’s build a few buttons by adding this code. When you hot reload app using CMD+R, you will see the app in the simulator. This app has a welcome text with a couple of buttons links to another screen. Now we have a basic React Native app ready for UI testing.

Configure Detox

As Detox is a grey-box UI testing framework, we have to add the Detox code inside the main app repository. Tools like Appium allow test developers to create separate repositories for testing code which doesn’t always fit for CI/CD pipelines. In order to enable the support for Detox, we have to install the applesimutils library and Detox command-line tools using the following commands.

$ brew tap wix/brew
$ brew install applesimutils
$ npm install -g detox-cli

Detox comes with great CLI tools, which can be used to set up and execute UI tests from the command line or from CI server.

React Natives project has a package.json file so we can add the Detox library to our project using the following command.

npm install detox --save-dev

This command will take a while to add the Detox to HelloDetox app. Once Detox is added to the package.json file, we need to configure our HelloDetox app to use the Detox UI test framework.

"detox": {
  "configurations": {
    "ios.sim.debug": {
      "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/HelloDetox.app",
      "build": "xcodebuild -project ios/HelloDetox.xcodeproj -scheme HelloDetox -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
      "type": "ios.simulator",
      "name": "iPhone "
    }
  }
}

The options aforementioned are specific to the iOS build artifacts which are usually generated in the ios/build directory. The parameter ‘build‘ is an actual command that runs when executing “detox build” from the command line. This is an xcodebuild command from the native Apple developer tool, some iOS projects use workspaces so you might need to adjust the command accordingly. Finally, you have to specify which simulator is needed for test execution.

That’s it for the initial configuration to enable Detox UI testing in the React Native apps.

Add Detox Tests for React Native Apps

Detox can be used with any test runner in the JavaScript. There are Jest and Mocha officially supported by Detox but Detox is not tightly coupled with none of them. As Jest is a recommended test runner for React Native, we will use Jest for setting up the Detox tests in our React Native app. Detox has a command-line way to generate the scaffolding code. Run the following command from the root of the project.

$ detox init -r jest

This command will create an “e2e” directory with the sample test code.

detox ui testing

At this point, you can modify the tests according to the requirement of our app. Remember, in order to enable the testability of the React Native app, you need to add Test ID for each UI element in your app. You can refer to the app.js file, where we get the Test ID for UI elements that we need to interact with.

Write Your First Detox Test for UI Testing

Now that we have all the scaffolding code to write our first Detox test, rename the e2e/firstTest.spec.jest file with something meaningful e.g helloDetox.spec.jest and write your first test to validate if the button click works and navigate to the correct screen. You can also validate if the welcome text exists on the screen.

Detox official documentation has a great guide on preparing your first detox test here. In summary, we have to remember the following things.

  • Prepare separate JavaScript file for scenarios as per the selected test runner.
  • Make sure you have Test ID added to enable the testability of the React Native app.
  • Identify unique UI element on the screen and assert that element exists on the screen.
  • Reset the app in between the scenarios if needed.

You can read the full preparation guide here. In our case, we have to add the following code to validate our requirements.

describe('HelloDetoxTest', () => {
  beforeEach(async () => {
     await device.reloadReactNative();
   });
  it('should have welcome screen', async () => {
    await expect(element(by.id('welcome'))).toBeVisible();
  });
  it('should show hello Rect after tap', async () => {
    await element(by.id('hello_react')).tap();
    await expect(element(by.text('React!!!'))).toBeVisible();
   });
  it('should show Detox screen after tap', async () => {
    await element(by.id('detox_button')).tap();
    await expect(element(by.text('Detox!!!'))).toBeVisible();
   });
});

This test validates that tapping on the Hello React button will navigate to the “React!!!” screen and tapping on the “Hello Detox” will navigate to the “Detox!!!” screen.

At this stage, we got our first Detox up and running. In order to execute the Detox tests, we have to build an app first using the command

$ detox build

This will execute the xcodebuild command that we have configured in the ‘build’ section of the detox configuration. This command can take a few minutes if you are building an app for the first time. Once the app is successfully built, we are ready to execute our tests by using the following command.

$ detox test

This command will execute all the tests inside our e2e directory and if all tests pass, you will see nicely formatted test output.

detox ui testing

Congratulations!. You have executed your first U test using Detox.

Pros and Cons of Detox for UI Testing

Detox Pro
  • Detox is highly debuggable than any other third-party UI test automation.
  • Detox can be integrated easily in any React Native app. The initial cost and efforts are much less than any other tools.
  • Detox is way faster than Appium or any other third-party tool as it syncs with the app.
  • Detox is easy to learn and has great API documentation to write and extend our test suite.
  • Community is growing fast.
Detox Cons
  • Android support is not great but it’s improving
  • No Real Testing for iOS
  • Web Views and Hybrid apps are not supported.
  • Few useful methods are missing like getting the text out of element or finding the coordinates.
  • Test reporting and screenshot ability aren’t great.

You can see that Detox has pros and cons but if it suits your project requirements then Detox is a faster and reliable choice for UI test automation.

What’s Next

Now that we have got our first Detox test up and running. The next logical step would be adding a few more UI test journeys of your app. The UI test which covers the end to end journey can give a lot of confidence. The techniques used in this post can be used for any React Native app. Detox can provide the increased testing speed and confidence needed for deploying any React Native apps.

Source Code

The full source code for this tutorial is available on Github in the HelloDetox repository. You can clone the repository and try executing the detox test using the following commands.

$ git clone https://github.com/Shashikant86/HelloDetox
$ cd HelloDetox 
$ detox build
$ detox test

If you have Detox and Xcode installed then you will see the tests running in your machine.

Conclusion

To improve your testing speed and confidence, the flakiness and slowness in UI testing need to be resolved. Tools like Detox can fulfill the speed and reliability of the UI tests to perform an end to end user journey of the React Native apps. Have you tried out Detox for mobile app testing? What is your experience of using Detox? Let us know.