React native end to end testing on CircleCI
Tags: reactnative, circleci, javascript, android
Published: 2020-09-24 14:30:10

---
title: React native end to end testing on CircleCI
published: true
description: Automating graybox E2E testing on CircleCI for RN app's using detox
tags: #reactnative, #circleci, #javascript, #android
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/keuldb9wkw7vvyhdvgol.png
---

## Setup Detox

There is an :zap: [article](https://dev.to/jeevankishore/e2e-detox-react-native-161o) dedicated to how to setup detox and it's know how's.

---

With Detox now being set, we would like it to run when ever there is a push to a branch. Let's say master.

For that, all we have to do is hook up our repo to CircleCI and :pencil: write some bit of configuration to get it started.

---

## CircleCI configuration

```yml
version: 2.1

commands:

  node-version:
    description: "Install node version 12"
    steps:
      - run:
          name: 'Install Project Node'
          command: |
            set +x
            source ~/.bashrc

            curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
            export NVM_DIR="$HOME/.nvm"
            [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
            [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"


            nvm install 12.13.0
            NODE_DIR=$(dirname $(which node))
            echo "export PATH=$NODE_DIR:\$PATH" >> $BASH_ENV

  npm-dependencies:
    description: "Get JavaScript dependencies"
    steps:
      - run:
          name: Executing node version check
          command: node -v
      - restore_cache:
          name: Restore npm cache
          key: v1-npm-{{ checksum "./package-lock.json" }}-{{ arch }}
      - run:
          working_directory: .
          name: Installing JavaScript dependencies
          command: npm install
      - save_cache:
          name: Save npm cache
          key: v1-npm-{{ checksum "./package-lock.json" }}-{{ arch }}
          paths:
            - ././node_modules

  bundle-dependencies:
    description: "Get bundle dependencies"
    steps:
      - restore_cache:
          name: Restore Fastlane cache
          key: v1-gems-{{ checksum "Gemfile.lock" }}-{{ arch }}
      - run:
          working_directory: .
          name: Download Fastlane dependencies
          command: bundle install --path ./vendor/bundle
      - save_cache:
          name: Save Fastlane cache
          key: v1-gems-{{ checksum "Gemfile.lock" }}-{{ arch }}
          paths:
            - ./vendor/bundle

  pods-dependencies:
    description: "Get cocoapods dependencies"
    steps:
      - restore_cache:
          name: Restore cocoapods specs and pods
          key: v1-cocoapods-{{ checksum "./ios/Podfile.lock" }}-{{ arch }}
      - run:
          name: Getting cocoapods dependencies
          working_directory: ./ios
          command: bundle exec pod install --deployment
      - save_cache:
          name: Save cocoapods specs and pods cache
          key: v1-cocoapods-{{ checksum "./ios/Podfile.lock" }}-{{ arch }}
          paths:
            - ./ios/Pods
            - ~/.cocoapods

  gradle-dependencies:
    description: "Get Gradle dependencies"
    steps:
      - run:
          working_directory: ./android
          name: Chmod permissions
          command: sudo chmod +x ./gradlew
      - restore_cache:
          name: Restore Gradle cache
          key: v1-gradle-{{ checksum "./android/build.gradle" }}-{{ checksum  "./android/app/build.gradle" }}-{{ arch }}
      - run:
          working_directory: ./android
          name: Download Gradle dependencies
          command: ./gradlew dependencies
      - save_cache:
          name: Save Gradle cache
          paths:
            - ~/.gradle
          key: v1-gradle-{{ checksum "./android/build.gradle" }}-{{ checksum  "./android/app/build.gradle" }}-{{ arch }}

  android-sdk-dependencies:
    description: "Install and set android SDK"
    steps:
      - run:
          name: set ANDROID_SDK_ROOT
          command: |
            echo 'export ANDROID_SDK_ROOT=$HOME/android-tools'  >> $BASH_ENV

      - restore_cache:
          key: android=tools-v1-{{ checksum "scripts/install-android-tools.sh" }}-{{ arch }}

      - run:
          name: install android tools
          command: |
            sh scripts/install-android-tools.sh
            echo 'export PATH=$ANDROID_SDK_ROOT/tools/bin:$PATH'  >> $BASH_ENV
            echo 'export PATH=$ANDROID_SDK_ROOT/tools:$PATH'  >> $BASH_ENV
            echo 'export PATH=$ANDROID_SDK_ROOT/platform-tools:$PATH'  >> $BASH_ENV
            echo 'export PATH=$ANDROID_SDK_ROOT/emulator:$PATH'  >> $BASH_ENV
            source $BASH_ENV
            sdkmanager --list

      - save_cache:
          key: android=tools-v1-{{ checksum "scripts/install-android-tools.sh" }}-{{ arch }}
          paths:
            - /Users/distiller/android-tools


  react-native-dependencies:
    description: "Install RN dependencies"
    steps:
      - run:
          name: "Install watchman"
          command: |
            HOMEBREW_NO_AUTO_UPDATE=1 brew install watchman


  simulator-dependencies:
    description: "Install iOS simulator dependencies"
    steps:
      - run:
          name: "Install applesimutils"
          command: |
            HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew
            HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils

  create-launch-android-emulator:
    description: "create and launch android emulators"
    steps:
      - run:
          name: create AVD
          command: echo "no" | avdmanager --verbose create avd --force --name "Pixel_3a_API_29" --package "system-images;android-29;google_apis;x86_64"

      - run:
          name: start AVD
          command: emulator @Pixel_3a_API_29 -no-window -no-audio
          background: true

      - run:
          name: wait for emulator
          command: adb wait-for-device shell 'while [[ -z $(getprop dev.bootcomplete) ]]; do sleep 1; done;'

  clear-detox-cache:
    description: "Clears detox framework cache"
    steps:
      - run:
          working_directory: .
          name: Clear detox cache
          command: |
            npx detox clean-framework-cache
            npx detox build-framework-cache


jobs:

  android-test:
    macos:
      xcode: 11.3.1
    steps:
      - attach_workspace:
          at: .
      - checkout
      - node-version
      - bundle-dependencies
      - npm-dependencies
      - react-native-dependencies
      - gradle-dependencies
      - android-sdk-dependencies
      - create-launch-android-emulator
      - clear-detox-cache

      - run:
          working_directory: .
          name: Run android detox build
          command: npx detox build -c android.emu.release

      - run:
          working_directory: .
          name: Run android detox test
          command: npx detox test -c android.emu.release --headless --record-logs all

      - store_artifacts:
          path: ././artifacts
          destination: ./jest-logs

      - store_artifacts:
          path: ././reports
          destination: ./reports


  ios-test:
    macos:
      xcode: 11.3.1
    steps:
      - attach_workspace:
          at: .
      - checkout
      - node-version
      - bundle-dependencies
      - npm-dependencies
      - pods-dependencies
      - react-native-dependencies
      - simulator-dependencies
      - clear-detox-cache

      - run:
          working_directory: .
          name: Run iOS detox build
          command: npx detox build -c ios.sim.release

      - run:
          working_directory: .
          name: Run iOS detox test
          command: npx detox test -c ios.sim.release --record-logs all > test-summary.txt

      - store_artifacts:
          path: ././artifacts
          destination: ./jest-logs

      - store_artifacts:
          path: ././reports
          destination: ./reports


workflows:
  version: 2

  run_detox_tests:
    jobs:
      - android-test
      - ios-test
```


Let's walk through some commands to get better context on what's happening:

```
      - attach_workspace:
          at: .
```
> Attach the workspace to the current directory


```   
   - checkout
```
> Pull the repo and checkout to the current branch


```
      - node-version
```
> Install node package and check for adequate versions


```
      - bundle-dependencies
```
> Install and cache gem bundle dependencies such as cocoapods


```
      - npm-dependencies
```
> Install and cache  npm depdendencies


```
      - pods-dependencies
```
> Install and cache  cocoapods dependencies


```
      - react-native-dependencies
```
> Install and cache  RN dependencies


```
      - simulator-dependencies
```
> Install simulator dependencies (android)


```
      - clear-detox-cache
```
> Clear existing cache of detox for every boot


Please visit the [repo](https://github.com/Jeevan-Kishore/e2e-detox) for a working demo

If you have questions, let us know in the comments and we are looking forward for your feedback 🍻