Detox: Superfast E2E React Native UI Testing
In this post, we create a simple React Native app that we then test using the open source Detox testing framework.
Join the DZone community and get the full member experience.
Join For FreeIn recent years, React Native has become a very popular technology in the cross-platform mobile application development race, 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 already known, the major problems in the mobile UI testing are slowness and flakiness. Tools like Appium are completely black-box and use client-server architecture which causes flakiness in UI tests. Detox is designed to solve the problem of slowness and flakiness for mobile UI testing. Some of Detox's great features are:
- 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 (learn how to automate Detox tests on Bitbar here).
- 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 a 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 apps is fairly simple. If you are already running your React Native apps, the basic requirements for running iOS and Android apps in the simulator must be fulfilled. In this tutorial, we will focus on iOS but Android specific setups are fairly easy once you get on with iOS. As a pre-requisite, you need a macOS machine 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:
- macOS with Xcode
- Homebrew
- Node
- React Native CLI and React Native App
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 Node installed, you should be able to access the 'npm' commands from the terminal. Now you can install React Native globally and create the 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.
Let's run the app inside the iOS simulator using the following commands:
$ 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 the 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 an app using CMD+R, you will see the app in the simulator. This app has a welcome text with a couple of buttons that link 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 the 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 Xʀ"
}
}
}
The aforementioned options 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 React Native apps.
Add Detox Tests for React Native Apps
Detox can be used with any test runner in JavaScript. Jest and Mocha are officially supported by Detox, but Detox is not tightly coupled with either 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.
At this point, you can modify the tests according to the requirements of our app. Remember, in order to enable the testability of the React Native app, you need to add a 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
Now that we have all the scaffolding code to write our first Detox test, rename the e2e/firstTest.spec.jest file to 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's official documentation has a great guide on preparing your first detox test here. In summary, we have to remember the following things:
- Prepare a separate JavaScript file for scenarios as per the selected test runner.
- Make sure you have a Test ID added to enable the testability of the React Native app.
- Identify a unique UI element on the screen and assert that 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" button will navigate to the "Detox!!!" screen.
At this stage, we got our first Detox app 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.
Congratulations! You have executed your first U test using Detox.
Pros and Cons of Detox
Detox Pro
- Detox is more 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.
- The 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.
- A few useful methods are missing, like getting the text out of the 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 fast 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 to add 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 on 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.
Published at DZone with permission of Shashikant Jagtap, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments