Appium Testing ReactNative for Android Emulator in Github Actions, Mar 2020

Sandeep Dinesh
5 min readMar 26, 2020

--

Github Action with Appium & Android Emulator

Ever since tasting defeat after defeat to setup a cloud based CI/CD pipeline using Android Emulators and Appium in the past, when Github Actions presented itself with its all its glory, I was frankly skeptical of the success. Given that at the time of writing this blog Github Actions is still work in progress, by their own admission, my point of the whole exercise was how far can I push it to make it happen. Hurray! The great news is that we CAN accomplish it and hence I am sharing this post.

Success Factors: The success factors which I attribute to Github Actions being able to make this happen are firstly their MacOS image, then the Android Studio configured within and finally full support for Javascript technologies from node to react.

Bear in mind that MacOS images are expensive, so plan your deployment according to the costing in your organization. Ubuntu images both in Github Actions and CircleCI do not support hardware acceleration, so emulators aren’t functionally useful for our testing purposes.

TLDR So let’s jump to coding.

So here’s the design/ plan of what we want to do.

  1. Every time a test node is boot up,
  2. Setup Android emulator and boot it,
  3. Install all dependencies (including Appium),
  4. Start Appium in Background,
  5. Boot up metro builder and Run it in background (More on this below),
  6. Build react-native app, and finally
  7. Run your tests.

Do note :In my case I am configuring my backend environment and mobile element test ids from a branch. So from metro builder, these gets loaded on to the mobile app when its build.

In case you are having a similar design, without step to boot your Metro builder, your app would boot up without these changes.

You can work with your development code to have deep links to backend environment of your choice and persistent test ids. In such cases, you can ignore that step

Sample YAML:


# Pre-Commit E2E Tests in Android
name: Pre-Commit E2E Tests in Android# Controls when the action will run.
on:
push:
branches: [ testbranch ]
pull_request:
branches: [ develop ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: macOS-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
with:
ref: testbranch
# Setup Node JS - 10.17.0
- name: Set up Node JS 10.17.0
uses: actions/setup-node@v1
with:
node-version: '10.17.0'
# Clean Packages & Install Dependencies
- name: Clean Packages
run: |
rm -rf node_modules
npm cache clean --force
rm -rf package-lock.json
# Install React Native CLI
- name: Install React Native CLI
run: |
npm install react-native-cli
# Run Android Emulator
- name: Run Android Emulator
run: |
echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;android-28;google_apis;x86_64'
echo "no" | $ANDROID_HOME/tools/bin/avdmanager create avd -n test_device -k 'system-images;android-28;google_apis;x86_64' --force
echo $ANDROID_HOME/emulator/emulator -list-avds
echo "Starting emulator"
nohup $ANDROID_HOME/emulator/emulator -avd test_device -no-snapshot > /dev/null 2>&1 &
$ANDROID_HOME/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]]; do sleep 1; done; input keyevent 82'
$ANDROID_HOME/platform-tools/adb devices
echo "Emulator started"
# Use HTTPS repos
- name: Use HTTPS repos
run: |
git config --global url."https://github".insteadOf ssh://git@github
# Install Repo and Dependencies
- name: Install Repo and Dependencies
run: |
npm install --save-dev
# Start the Appium Server
- name: Start the Appium Server
run: ./node_modules/.bin/appium --log-timestamp --log-no-colors --allow-insecure chromedriver_autodownload > appium.log &
# Poll for Appium Server to Start
- name: Poll for Appium Server to Start
run: |
until $(curl --output /dev/null --silent --head --fail http://127.0.0.1:4723/wd/hub/sessions); do
sleep 5
done
# Open Metro Bundler in Background
- name: Open Metro Bundler in Background
run: |
node_modules/react-native/scripts/launchPackager.command &
# Build Android App and Run Tests
- name: Build Android App and Run Tests
env:
E2E_TEST_PLATFORM: 'android'
E2E_TEST_DEFAULTS: 'true'
E2E_TEST_TAGS: 'E2E'
run: |
react-native run-android
sleep 15
npm run e2e-test
# Upload Appium Logs
- name: Upload Appium logs
uses: actions/upload-artifact@v1
with:
name: appium.log
path: appium.log
# Upload Test Results
- name: Upload Test Results
uses: actions/upload-artifact@v1
with:
name: e2e-results
path: __tests__/e2e/output
Android Emulator Startup
Metro Sever Bootup

Explanations:

  1. I have configured ‘e2e-test’ as a script in my package.json also the results will be available under ‘__tests__/e2e/output’.
  2. Appium is added as part of my dependencies, so it will be installed in ‘npm install --save-dev’
  3. I have few dependencies which don’t git clone in ssh mode, to overcome it I am forcing ‘Use HTTPS repos’ step, in your case it could be optional.
  4. Finally, if you are using Artifactory in your repo, you can add these steps before ‘Use HTTPS repos’ or ‘Install Repo and Dependencies’ step as explained in previous step

# Install Login CMD
- name: Install npm-login-cmd
run: |
npm install -g npm-login-cmd
# Config Registry
- name: Config Registry
run: |
npm config set registry '${{ secrets.ARTIFACTORY_REGISTRY }}' # Login to NPM Repo
- name: npm login
env:
NPM_USER: ${{ secrets.ARTIFACTORY_USERNAME }}
NPM_PASS: ${{ secrets.ARTIFACTORY_PASSWORD }}
NPM_EMAIL: ${{ secrets.ARTIFACTORY_EMAIL }}
run: |
npm-login-cmd

Test Results

Test Results

Finally, I have found these tests to be some times flakey, as its always associated with every Appium based tests. Given that I have web views in my app, I am still sticking with Appium for now. Eventually, when my web views either vanish/ Detox add support for it, this seems to be the best bet for automated mobile testing for now. Cheers, Happy Test Automation!

--

--