React Native End to End Testing with Detox
Tags: reactnative, react, mobiledevelopment, javascript
Published: 2019-08-21 15:07:15

---
title: 'React Native End to End Testing with Detox'
published: true
description: 'When you have common user flows that need to be tested Detox can provide the means to quickly and consistently do so.'
tags: React Native, React, Mobile Development, JavaScript
canonical_url: https://www.reactnativeschool.com/react-native-end-to-end-testing-with-detox
---

> This post was originally published on [React Native School](https://www.reactnativeschool.com/react-native-end-to-end-testing-with-detox).

In our continuation of testing month here at React Native School we're going to take one step further and cover End to End (E2E) testing. Previously we covered:

- [Component Testing with React Native Testing Library](https://learn.handlebarlabs.com/courses/426773/lectures/11360156)
- [Mocking Fetch API Calls When Using Jest](https://www.reactnativeschool.com/mocking-fetch-api-calls-when-using-jest)
- [Test Driven Development with AsyncStorage](https://learn.handlebarlabs.com/courses/426773/lectures/11143625)

To accomplish this we'll be using the [Detox library from Wix](https://github.com/wix/Detox). This is a powerful library but I would be lying if I said it was easy to setup manage. I've used it on multiple projects but not extensively - it was just too much to manage/maintain for me at this point.

That said, I feel testing month would be incomplete without covering it because it is the go-to tool for E2E testing.

Detox is physically going to boot up a simulator and click in your app (really fast). It's the most real testing can get.

## Setup

> **Note:** I've only used Detox on iOS before. It's supposed to work on Android as well but I haven't tried it.

Rather than spending a thousand words creating a basic React Native project I'm going to go ahead and assume you can do that. If not, you probably don't need to be reading this lesson yet. Get familiar with React Native and then come back to this in the future.

I have an [example project](https://github.com/ReactNativeSchool/testing-example) that has detox tests and other included that you can reference.

All the app does is make a fetch request for a list of posts and then renders them. You can click on any post and then view that post in detail.

[The project is available on Github](https://github.com/ReactNativeSchool/testing-example). It's the same one I've been using for all my testing lessons this month.

The two files you should be familiar with are [PostList.js](https://github.com/ReactNativeSchool/testing-example/blob/master/App/screens/PostList.js) and [Post.js](https://github.com/ReactNativeSchool/testing-example/blob/master/App/screens/Post.js).

Detox has a [comprehensive getting started guide](https://github.com/wix/Detox/blob/master/docs/Introduction.GettingStarted.md) that you'll need to reference as you go. Below are a few of the highlights.

After you've installed the CLI globally, you need to install detox to your project

<p class="code-header">Terminal</p>

```jsx
yarn add --dev detox
```

And it's configuration to package.json.

<p class="code-header">package.json</p>

```json
{
  // ...
  "detox": {
    "configurations": {
      "ios.sim.debug": {
        "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/CHANGE_THIS.app",
        "build": "xcodebuild -workspace ios/CHANGE_THIS.xcworkspace -scheme CHANGE_THIS -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
        "type": "ios.simulator",
        "name": "iPhone 7"
      }
    }
  }
}
```

**NOTE:** You need to replace `CHANGE_THIS` in the above snippet to your project name. More info can be found [here](https://github.com/wix/Detox/blob/master/docs/Introduction.GettingStarted.md#2-add-detox-config-to-packagejson).

Finally you initialize the default test and configuration.

<p class="code-header">Terminal</p>

```bash
detox init -r jest
```

Doing this will create an `e2e` folder at the root of the project.

## Writing a Detox Test

First, delete `e2e/firstTest.spec.js` and then create `PostList.spec.js`.

I keep all E2E tests in the root `e2e/` folder so that I can easily filter them out when I want to run the tests that I run more often (`jest . --testPathIgnorePatterns e2e/ node_modules/`).

Since we're using Jest as the test runner much of this will look similar to what we've been covering this month. What detox is going to do is expose some additional globals to interact with our app.

First the scaffolding.

<p class="code-header">e2e/PostList.spec.js</p>

```jsx
describe('PostList', () => {
  beforeEach(async () => {
    await device.reloadReactNative();
  });

  it('render a tappable list of posts', async () => {});
});
```

Before each detox test runs we want to reload React Native (the equivalent of pressing cmd + r) so that the next test is somewhat independent of the previous. I say somewhat because the app is physically be installed and will have things saved in storage from the previous tests. Regardless, reloading before the next test is a best practice.

Now for the actual test. If you're a React Native School pro member than these tests may look very similar to what we wrote last week for integration tests. This time however the tests are physically running on a device.

<p class="code-header">e2e/PostList.spec.js</p>

```jsx
describe('PostList', () => {
  beforeEach(async () => {
    await device.reloadReactNative();
  });

  it('render a tappable list of posts', async () => {
    await expect(element(by.id('post-list'))).toBeVisible();
    await waitFor(element(by.id('post-row-0')))
      .toBeVisible()
      .withTimeout(2000);
    await element(by.id('post-row-0')).tap();
    await expect(element(by.id('post-title'))).toBeVisible();
  });
});
```

`element` and `by.id` are coming to us from Detox. We can then use those results to interact/analyze our app.

First we check that our `post-list` component exists. We're then going to wait for a post row to exist. We're actually going to hit our API in this test. This is probably a good thing because we want to test the actual app (E2E tests are just there to replace your manual tapping through the app). Also, I can't figure out how to mock an API response in Detox so this is all we can do :).

Once that's visible we want to tap it, bringing us to the next screen. On that screen (`Post.js`) there should be a `post-title` and it should be visible. If all those conditions pass then our test passes!

## Running Tests

First you'll want to build the app for detox by running `detox build`.

To actually run the app you'll run `detox test`.

This should boot a simulator and start tapping!

![Test running](https://www.reactnativeschool.com/static/01-4637815082d93f542486b6e7cab95e60.gif)

It may look like me tapping in the app but I assure you it's detox doing the work!

![Test success](https://www.reactnativeschool.com/static/06ac96a5feba90c056fd929db6d1d883/62b80/02.png)

## Summary

Detox can be a bit of a pain to setup and manage but it is very powerful. If you've got some common user flows that need to be tested thoroughly then you could replace yourself doing that before each release with a few convenient Detox tests.

## Additional Resources

- [Detox](https://github.com/wix/Detox)
- [Example with the above code](https://github.com/ReactNativeSchool/testing-example)