React Native e2e testing with DETOX.

Marcin Górecki
DNA Technology
Published in
6 min readJan 5, 2022

So, there is this: I’m a frontend developer, previously working with React, Vue, TypeScript and some other fancy libraries. Back in the days I built an app or two with PhoneGap and Cordova, but those are the echoes of the past now, and with the advent of Flutter and with React Native being around for so long — there was really no excuse for me but to dig deeper into mobile development which for years has been the quickest growing branch in development industry. And I was quite happy with both Flutter and React Native until the need of testing occured.

Where are my tools?

You know what is great about being a frontend developer? If you have a problem there is a 99,9% chance someone has already solved it for you. You need to deal with data parsing? Oh, there is only a million libraries to do that for you. You need to validate or manipulate your data? Same! And it goes for testing as well: unit testing, integrated testing and e2e — all is covered with various tools plus you have a bunch of stuff to monitor your web app in real time or validate its functionality — from Lighthouse to Yslow and add-ons.

Well this isn’t true for mobile development at all.
At first I was quite happy: I used react-native-testing-library for unit testing and it worked great. Imagine my surprise when I couldn’t find at least five e2e testing libraries for RN. Whaaaat? Where are my tools? Well, all good things come to an end.

Appium or Detox

Those two seemed to be the only viable choice. Based on several comparisons (like here) I decided to go for Detox — easier to set up and designed to work with JS (most examples I found for Appium were in JAVA). I also liked the idea of grey-box testing. Apart from checking the outer behavior of the software Detox can easily check data flow and that seems reasonable for any e2e testing. I had a feeling that overally the quality of the software might benefit from such approach. So, yeah: Detox it is.

NOTE: at the time of writing this article — December 2021 — Detox has some serious issues working with both Android devices and emulators, especially on Macs with M1 chip. I’m sure the problem will be solved soon, but for now I’m gonna focus on iOS only.

Detox setup

HERE is a ready app with Detox attached and some tests prepared in case you need a quick starter and just want to see testing magic in action. Follow the steps from README to have it up and running. It is done with React Native CLI and this is the recommended approach as Detox doesn’t officially support Expo. (Still — no worries, here is a community version of Detox available for Expo apps as well).

If however you want to go through the whole process step-by-step, then create a React Native app with CLI (check the guide HERE) and then in your app root folder install Detox CLI, library itself and a test runner (you are going to need Node and Homebrew installed obviously):

$ xcode-select --install
$ brew tap wix/brew
$ brew install applesimutils
$ npm install -g detox-cli
$ npm install detox jest-circus --save-dev

Once all the tools are installed (and detox appears in you node_modules) let’s add some boilerplate files:

$ detox init -r jest

This creates e2e folder as well as .detoxrc.json file at the root of our app. And we gonna focus on that file in the first place.

For the sample app I linked above the file looks like this:

I called my sample app mockapp and you should replace every occurence of this title in the file with your app’s name.

You need iOS simulator to run Detox tests as it currently doesn’t support testing on real devices (at least for Apple). If you don’t have a simulator already install it using your Xcode (⇧ + ⌘ + 2 ). I have iPhone 13 installed, but you may choose a different simulator — in that case change also its type in your .detixrc.json file.

Change simulator’s type in .detoxrc.json if needed.

And now with our .detoxrc.json file ready we can move to…

Writing our first tests

Let’s look into e2e folder that has been created by Detox initialization. There should be a file named firstTest.e2e.js. Delete whatever is inside and add the following:

If your linter goes crazy about the file — don’t worry. Find the .eslintrc.js file at the root of your app (if you created app with React Native CLI — it should be there by default) and add Detox to ‘plugins’ array like so:

But there is one thing we absolutely MUST do. In the test we are telling Detox to find element by its ID, so obviously we must add the ID to our component so that it is identifiable. React accepts ‘testID’ argument for all its elements, so just add that to your main wrapper:

And before running the test we must actually build the app for Detox:

$ detox build -c ios 

After a minute or two the build should be ready. This step needs to be done only once. And then we can finally run the test:

$ detox test -c ios 

That should run the app on your simulator along with logging test results to your console. Of course checking if element is visible on the page is not that impressive, so if you still didn’t run the app and tests from THIS REPO— do it now.

This is the behavior of Detox running the tests on iOS simulator. As you see the example is a bit more complex than checking simple visibility. It works with ID and text identification, automatic typing and deleting random texts, checking buttons functionality and swipes.

What is Detox good for anyway?

You now have a working example of a test. Feel free to play around with that. Check out the DOCS for API reference. What caught my eye was quite rich choice of actions available: apart from swipes and taps Detox can simulate pinches, long presses, multitaps, drag’n’drop, interaction with forms, date pickers, taking screenshots and several others. It can check elements’ exitence, visibility, scroll depth, focus, value and more. And it can identify elements by different properties (in my example i use only text and id). What is more: it can mock receiving and interacting with notifications, detect opening particular URLs, mimic user’s interaction with our app and take snapshots of the screen in different states. With all that Detox should be sufficient to test any app at least for happy paths and overall user experience.

What may go wrong?

Detox setup seems not too complex, but it has several gotchas that can be easily avoided. So:

Proper JAVA version

Check what JAVA version you have installed on your machine:

$ /usr/libexec/java_home -V

It is possible that you have several versions available, so make sure you use JAVA 1.8. Others will not work with RN and Detox. You can set default JAVA version to 1.8 in your .bashrc or .zshrc files but you can also type:

$ export JAVA_HOME=`/usr/libexec/java_home -v 1.8`

…and that will work as well.

Proper paths in .detoxrc

I went through a bunch of blogposts and tutorials and some of them recommended to use .xodeproj instead of .xcodeworspace. Don’t do it! Detox won’t work with the former. Stick to the paths shown in the gist above.

Tests fail because of timeout

That may happen if you perform a long test — a hint here: split your tests into separate files. Every file with e2e.js extension from e2e folder will be run subsequently. Alternatively you can change the value of ‘testTimeout’ property in e2e/config.json. But this not the preferred way.

And that’s that! You now know the basics of Detox — give it a try. I did and I don’t regret. And once the Android devices will run the tests as expected — it will be hard to beat. Enjoy!

--

--

Marcin Górecki
DNA Technology

Software developer at DNA Technology. Focusing mainly on front-end and mobile development.