Writing e2e tests with React Native
Testing with React Native is something that I was always interested in. Being responsible for releasing several apps in our office, I follow a set of repetitive instructions to make sure that app is not going to break after upgrading. It’s good to look into ways to automate this process, so it is easier, faster and less error-prone.
To this day, there was never really a dedicated framework created with React Native in mind. There were native snapshots that Mike Grabowski blogged about last year, jest snapshots from Ferran Negre, cavy and appium e2e tests. Native snapshots and jest snapshots have been utilised in React Native core repository, adding precious value and confidence into the release pipeline.
However, none of them allowed me to turn on RNTester (react native official example app), click around and make sure we didn’t break Camera API or the bridge.
Detox is a brand new end-to-end test and automation library for React Native. Behind the scenes for testing is uses native solutions, Espressofor Android and EarlGrey for iOS. It runs your app on a simulator and gives you complete freedom to perform assertions on a real interface and interact with it by simulating arbitrary events. What’s great in Detox that it is a promise library so you don’t really care about <rte-code>wait(int) / timeouts<rte-code> like in Appium during e2etest.
Few months ago I was facing “timeout problem” when mobile app was working with some external printers whose printing time was depending on bluetooth / internet / usb connection. It was almost impossible to estimate printing time for one label when stretch test was about 1000 labels to print and if one of the printings took longer the test was broken.With promises I don’t need to specify time for action and test will not fail when connection breaks for a sec.
Cavy is an alternative that appeared recently as well, but the fact that it depends on <rte-code>refs<rte-code> made me advocate for Detox, since it presents a nicer API. Cavy also tests only your JavaScript part of code, not native one like Detox. Wix library also seems to be much faster while it’s working on web sockets. These things convinced me to give it a go!
It integrates well with your existing testing framework and it essentially boils down to the following:
Don’t worry if it looks cryptic at first. We will get to it at the end of this article.
The official documentation suggests using Mocha. In this example, I’ll show you how to set it up with Jest, which comes with every React Native app by default.
Getting started
The quickest way to get started is to follow official documentation (Step 1 and Step 2). We are going to skip Step 3 as its tightly coupled to Mocha. The installation instructions look complex, but in reality, it turned out to be a really smooth process.
We will start by adding Jest to our dependencies:
In my case, I have created 3 folders:
- <rte-code>jest<rte-code> that contains setup files
- <rte-code>__e2e__<rte-code> that contains our Detox tests
- <rte-code>__tests__<rte-code> that contains other Jest tests
Now, in order to use Detox for all tests inside <rte-code>__e2e__<rte-code> folder, we need to integrate it with Jest. We can do it in every test file, but that would be a bit cumbersome.
What we can do instead is to set the following in package.json:
Here, setupTestFrameworkScriptFile can be used to configure testing framework right before the test suite is going to be run. It’s a nice alternative to repeating config in every file.
The following setup.js file is straight copy from official documentation with an exception that we use Jest API instead of Mocha one:
And that’s it! You are all set!
You can browse the full example in Mike’s repository.
Writing tests
Before interacting with your components, you have to give them a name so that the testing framework can interact with it. This can be done by setting a special <rte-code>testID<rte-code> prop on any built-in React Native component.
Both platforms in native implementations has setter for <rte-code>testID<rte-code>
In Android:
In iOS:
For example, let’s make sure that default React Native app has a Welcome to React Native heading.
To do so, we first are going to open index.ios.js and set testID to welcome:
Now, lets create a <rte-code>__e2e__/welcome.spec.js<rte-code> file and make sure the content is visible:
And that’s it! You can now run:
To see the results of your work.
You can browse the rest of Detox API to explore different matchers and expectations.
I wrote this article together with Mike, so big shout out to Grabbou 🎉🎉🎉
Here's a link to the final repo.