• United States+1
  • United Kingdom+44
  • Afghanistan (‫افغانستان‬‎)+93
  • Albania (Shqipëri)+355
  • Algeria (‫الجزائر‬‎)+213
  • American Samoa+1684
  • Andorra+376
  • Angola+244
  • Anguilla+1264
  • Antigua and Barbuda+1268
  • Argentina+54
  • Armenia (Հայաստան)+374
  • Aruba+297
  • Australia+61
  • Austria (Österreich)+43
  • Azerbaijan (Azərbaycan)+994
  • Bahamas+1242
  • Bahrain (‫البحرين‬‎)+973
  • Bangladesh (বাংলাদেশ)+880
  • Barbados+1246
  • Belarus (Беларусь)+375
  • Belgium (België)+32
  • Belize+501
  • Benin (Bénin)+229
  • Bermuda+1441
  • Bhutan (འབྲུག)+975
  • Bolivia+591
  • Bosnia and Herzegovina (Босна и Херцеговина)+387
  • Botswana+267
  • Brazil (Brasil)+55
  • British Indian Ocean Territory+246
  • British Virgin Islands+1284
  • Brunei+673
  • Bulgaria (България)+359
  • Burkina Faso+226
  • Burundi (Uburundi)+257
  • Cambodia (កម្ពុជា)+855
  • Cameroon (Cameroun)+237
  • Canada+1
  • Cape Verde (Kabu Verdi)+238
  • Caribbean Netherlands+599
  • Cayman Islands+1345
  • Central African Republic (République centrafricaine)+236
  • Chad (Tchad)+235
  • Chile+56
  • China (中国)+86
  • Christmas Island+61
  • Cocos (Keeling) Islands+61
  • Colombia+57
  • Comoros (‫جزر القمر‬‎)+269
  • Congo (DRC) (Jamhuri ya Kidemokrasia ya Kongo)+243
  • Congo (Republic) (Congo-Brazzaville)+242
  • Cook Islands+682
  • Costa Rica+506
  • Côte d’Ivoire+225
  • Croatia (Hrvatska)+385
  • Cuba+53
  • Curaçao+599
  • Cyprus (Κύπρος)+357
  • Czech Republic (Česká republika)+420
  • Denmark (Danmark)+45
  • Djibouti+253
  • Dominica+1767
  • Dominican Republic (República Dominicana)+1
  • Ecuador+593
  • Egypt (‫مصر‬‎)+20
  • El Salvador+503
  • Equatorial Guinea (Guinea Ecuatorial)+240
  • Eritrea+291
  • Estonia (Eesti)+372
  • Ethiopia+251
  • Falkland Islands (Islas Malvinas)+500
  • Faroe Islands (Føroyar)+298
  • Fiji+679
  • Finland (Suomi)+358
  • France+33
  • French Guiana (Guyane française)+594
  • French Polynesia (Polynésie française)+689
  • Gabon+241
  • Gambia+220
  • Georgia (საქართველო)+995
  • Germany (Deutschland)+49
  • Ghana (Gaana)+233
  • Gibraltar+350
  • Greece (Ελλάδα)+30
  • Greenland (Kalaallit Nunaat)+299
  • Grenada+1473
  • Guadeloupe+590
  • Guam+1671
  • Guatemala+502
  • Guernsey+44
  • Guinea (Guinée)+224
  • Guinea-Bissau (Guiné Bissau)+245
  • Guyana+592
  • Haiti+509
  • Honduras+504
  • Hong Kong (香港)+852
  • Hungary (Magyarország)+36
  • Iceland (Ísland)+354
  • India (भारत)+91
  • Indonesia+62
  • Iran (‫ایران‬‎)+98
  • Iraq (‫العراق‬‎)+964
  • Ireland+353
  • Isle of Man+44
  • Israel (‫ישראל‬‎)+972
  • Italy (Italia)+39
  • Jamaica+1876
  • Japan (日本)+81
  • Jersey+44
  • Jordan (‫الأردن‬‎)+962
  • Kazakhstan (Казахстан)+7
  • Kenya+254
  • Kiribati+686
  • Kosovo+383
  • Kuwait (‫الكويت‬‎)+965
  • Kyrgyzstan (Кыргызстан)+996
  • Laos (ລາວ)+856
  • Latvia (Latvija)+371
  • Lebanon (‫لبنان‬‎)+961
  • Lesotho+266
  • Liberia+231
  • Libya (‫ليبيا‬‎)+218
  • Liechtenstein+423
  • Lithuania (Lietuva)+370
  • Luxembourg+352
  • Macau (澳門)+853
  • Macedonia (FYROM) (Македонија)+389
  • Madagascar (Madagasikara)+261
  • Malawi+265
  • Malaysia+60
  • Maldives+960
  • Mali+223
  • Malta+356
  • Marshall Islands+692
  • Martinique+596
  • Mauritania (‫موريتانيا‬‎)+222
  • Mauritius (Moris)+230
  • Mayotte+262
  • Mexico (México)+52
  • Micronesia+691
  • Moldova (Republica Moldova)+373
  • Monaco+377
  • Mongolia (Монгол)+976
  • Montenegro (Crna Gora)+382
  • Montserrat+1664
  • Morocco (‫المغرب‬‎)+212
  • Mozambique (Moçambique)+258
  • Myanmar (Burma) (မြန်မာ)+95
  • Namibia (Namibië)+264
  • Nauru+674
  • Nepal (नेपाल)+977
  • Netherlands (Nederland)+31
  • New Caledonia (Nouvelle-Calédonie)+687
  • New Zealand+64
  • Nicaragua+505
  • Niger (Nijar)+227
  • Nigeria+234
  • Niue+683
  • Norfolk Island+672
  • North Korea (조선 민주주의 인민 공화국)+850
  • Northern Mariana Islands+1670
  • Norway (Norge)+47
  • Oman (‫عُمان‬‎)+968
  • Pakistan (‫پاکستان‬‎)+92
  • Palau+680
  • Palestine (‫فلسطين‬‎)+970
  • Panama (Panamá)+507
  • Papua New Guinea+675
  • Paraguay+595
  • Peru (Perú)+51
  • Philippines+63
  • Poland (Polska)+48
  • Portugal+351
  • Puerto Rico+1
  • Qatar (‫قطر‬‎)+974
  • Réunion (La Réunion)+262
  • Romania (România)+40
  • Russia (Россия)+7
  • Rwanda+250
  • Saint Barthélemy (Saint-Barthélemy)+590
  • Saint Helena+290
  • Saint Kitts and Nevis+1869
  • Saint Lucia+1758
  • Saint Martin (Saint-Martin (partie française))+590
  • Saint Pierre and Miquelon (Saint-Pierre-et-Miquelon)+508
  • Saint Vincent and the Grenadines+1784
  • Samoa+685
  • San Marino+378
  • São Tomé and Príncipe (São Tomé e Príncipe)+239
  • Saudi Arabia (‫المملكة العربية السعودية‬‎)+966
  • Senegal (Sénégal)+221
  • Serbia (Србија)+381
  • Seychelles+248
  • Sierra Leone+232
  • Singapore+65
  • Sint Maarten+1721
  • Slovakia (Slovensko)+421
  • Slovenia (Slovenija)+386
  • Solomon Islands+677
  • Somalia (Soomaaliya)+252
  • South Africa+27
  • South Korea (대한민국)+82
  • South Sudan (‫جنوب السودان‬‎)+211
  • Spain (España)+34
  • Sri Lanka (ශ්‍රී ලංකාව)+94
  • Sudan (‫السودان‬‎)+249
  • Suriname+597
  • Svalbard and Jan Mayen+47
  • Swaziland+268
  • Sweden (Sverige)+46
  • Switzerland (Schweiz)+41
  • Syria (‫سوريا‬‎)+963
  • Taiwan (台灣)+886
  • Tajikistan+992
  • Tanzania+255
  • Thailand (ไทย)+66
  • Timor-Leste+670
  • Togo+228
  • Tokelau+690
  • Tonga+676
  • Trinidad and Tobago+1868
  • Tunisia (‫تونس‬‎)+216
  • Turkey (Türkiye)+90
  • Turkmenistan+993
  • Turks and Caicos Islands+1649
  • Tuvalu+688
  • U.S. Virgin Islands+1340
  • Uganda+256
  • Ukraine (Україна)+380
  • United Arab Emirates (‫الإمارات العربية المتحدة‬‎)+971
  • United Kingdom+44
  • United States+1
  • Uruguay+598
  • Uzbekistan (Oʻzbekiston)+998
  • Vanuatu+678
  • Vatican City (Città del Vaticano)+39
  • Venezuela+58
  • Vietnam (Việt Nam)+84
  • Wallis and Futuna+681
  • Western Sahara (‫الصحراء الغربية‬‎)+212
  • Yemen (‫اليمن‬‎)+967
  • Zambia+260
  • Zimbabwe+263
  • Åland Islands+358
Thanks! We'll be in touch in the next 12 hours
Oops! Something went wrong while submitting the form.

Test Automation in React Native apps using Appium and WebdriverIO

Pushkar Deshpande

Full-stack Development

React Native provides a mobile app development experience without sacrificing user experience or visual performance. And when it comes to mobile app UI testing, Appium is a great way to test indigenous React Native apps out of the box. Creating native apps from the same code and being able to do it using JavaScript has made Appium popular. Apart from this, businesses are attracted by the fact that they can save a lot of money by using this application development framework.

In this blog, we are going to cover how to add automated tests for React native apps using Appium & WebdriverIO with a Node.js framework. 

What are React Native Apps

React Native is an open-source framework for building Android and iOS apps using React and local app capabilities. With React Native, you can use JavaScript to access the APIs on your platform and define the look and behavior of your UI using React components: lots of usable, non-compact code. In the development of Android and iOS apps, “viewing” is the basic building block of a UI: this small rectangular object on the screen can be used to display text, photos, or user input. Even the smallest detail of an app, such as a text line or a button, is a kind of view. Some views may contain other views.

What is Appium

Appium is an open-source tool for traditional automation, web, and hybrid apps on iOS, Android, and Windows desktop mobile platforms. Indigenous apps are those written using iOS and Android. Mobile web applications are accessed using a mobile browser (Appium supports Safari for iOS apps and Chrome or the built-in 'Browser' for Android apps). Hybrid apps have a wrapper around "web view"—a traditional controller that allows you to interact with web content. Projects like Apache Cordova make it easy to build applications using web technology and integrate it into a traditional wrapper, creating a hybrid application.

Importantly, Appium is "cross-platform", allowing you to write tests against multiple platforms (iOS, Android), using the same API. This enables code usage between iOS, Android, and Windows test suites. It runs on iOS and Android applications using the WebDriver protocol.

Fig:- Appium Architecture

What is WebDriverIO

WebdriverIO is a next-gen browser and Node.js automated mobile testing framework. It allows you to customize any application written with modern web frameworks for mobile devices or browsers, such as React, Angular, Polymeror, and Vue.js.

WebdriverIO is a widely used test automation framework in JavaScript. It has various features like it supports many reports and services, Test Frameworks, and WDIO CLI Test Runners

The following are examples of supported services:

  • Appium Service
  • Devtools Service
  • Firefox Profile Service
  • Selenium Standalone Service
  • Shared Store Service
  • Static Server Service
  • ChromeDriver Service
  • Report Portal Service
  • Docker Service

The followings are supported by the test framework:

  • Mocha
  • Jasmine
  • Cucumber 
Fig:- WebdriverIO Architecture

Key features of Appium & WebdriverIO

Appium

  • Does not require application source code or library
  • Provides a strong and active community
  • Has multi-platform support, i.e., it can run the same test cases on multiple platforms
  • Allows the parallel execution of test scripts
  • In Appium, a small change does not require reinstallation of the application
  • Supports various languages like C#, Python, Java, Ruby, PHP, JavaScript with node.js, and many others that have a Selenium client library

WebdriverIO 

  • Extendable
  • Compatible
  • Feature-rich 
  • Supports modern web and mobile frameworks
  • Runs automation tests both for web applications as well as native mobile apps.
  • Simple and easy syntax
  • Integrates tests to third-party tools such as Appium
  • 'Wdio setup wizard' makes the setup simple and easy
  • Integrated test runner

Installation & Configuration

$ mkdir Demo_Appium_Project

  • Create a sample Appium Project

$ npm init
$ package name: (demo_appium_project) demo_appium_test
$ version: (1.0.0) 1.0.0
$ description: demo_appium_practice
$ entry point: (index.js) index.js
$ test command: "./node_modules/.bin/wdio wdio.conf.js"
$ git repository:
$ keywords:
$ author: Pushkar
$ license: (ISC) ISC

This will also create a package.json file for test settings and project dependencies.

  • Install node packages

$ npm install
view raw node_package hosted with ❤ by GitHub

  • Install Appium through npm or as a standalone app.

$ npm install -g appium or npm install --save appium
view raw install_appium hosted with ❤ by GitHub

  • Install WebdriverIO

$ npm install -g webdriverio or npm install --save-dev webdriverio @wdio/cli

  • Install Chai Assertion library 

$ npm install -g chai or npm install --save chai
view raw install_chai hosted with ❤ by GitHub

Make sure you have following versions installed: 

$ node --version - v.14.17.0
$ npm --version - 7.17.0
$ appium --version - 1.21.0
$ java --version - java 16.0.1
$ allure --version - 2.14.0

WebdriverIO Configuration 

The web driver configuration file must be created to apply the configuration during the test Generate command below project:

$ npx wdio config
view raw wdio_config hosted with ❤ by GitHub

With the following series of questions, install the required dependencies,

$ Where is your automation backend located? - On my local machine
$ Which framework do you want to use? - mocha
$ Do you want to use a compiler? No!
$ Where are your test specs located? - ./test/specs/**/*.js
$ Do you want WebdriverIO to autogenerate some test files? - Yes
$ Do you want to use page objects (https://martinfowler.com/bliki/PageObject.html)? - No
$ Which reporter do you want to use? - Allure
$ Do you want to add a service to your test setup? - No
$ What is the base url? - http://localhost
view raw wdio_config hosted with ❤ by GitHub

This is how wdio.conf.js looks:

exports.config = {
port: 4724,
path: '/wd/hub/',
runner: 'local',
specs: ['./test/specs/*.js'],
maxInstances: 1,
capabilities: [
{
platformName: 'Android',
platformVersion: '11',
appPackage: 'com.facebook.katana',
appActivity: 'com.facebook.katana.LoginActivity',
automationName: 'UiAutomator2'
}
],
services: [
[
'appium',
{
args: {
relaxedSecurity: true
},
command: 'appium'
}
]
],
logLevel: 'debug',
bail: 0,
baseUrl: 'http://localhost',
waitforTimeout: 10000,
connectionRetryTimeout: 90000,
connectionRetryCount: 3,
framework: 'mocha',
reporters: [
[
'allure',
{
outputDir: 'allure-results',
disableWebdriverStepsReporting: true,
disableWebdriverScreenshotsReporting: false
}
]
],
mochaOpts: {
ui: 'bdd',
timeout: 60000
},
afterTest: function(test, context, { error, result, duration, passed, retries }) {
if (!passed) {
browser.takeScreenshot();
}
}
}
view raw wdio.conf.js hosted with ❤ by GitHub

For iOS Automation, just add the following capabilities in wdio.conf.js & the Appium Configuration: 

{
"platformName": "IOS",
"platformVersion": "14.5",
"app": "/Your_PATH/wdioNativeDemoApp.app",
"deviceName": "iPhone 12 Pro Max"
}
view raw ios.conf.js hosted with ❤ by GitHub

Launch the iOS Simulator from Xcode

Install Appium Doctor for iOS by using following command:

npm install -g appium-doctor

Fig:- Appium Doctor Installed

This is how package.json will look:

{
"name": "demo_appium_test",
"version": "1.0.0",
"description": "demo_appium_practice",
"main": "index.js",
"scripts": {
"test": "./node_modules/.bin/wdio wdio.conf.js"
},
"author": "Pushkar",
"license": "ISC",
"dependencies": {
"@wdio/sync": "^7.7.4",
"appium": "^1.21.0",
"chai": "^4.3.4",
"webdriverio": "^7.7.4"
},
"devDependencies": {
"@wdio/allure-reporter": "^7.7.3",
"@wdio/appium-service": "^7.7.3",
"@wdio/cli": "^7.7.4",
"@wdio/local-runner": "^7.7.4",
"@wdio/mocha-framework": "^7.7.4",
"@wdio/selenium-standalone-service": "^7.7.4"
}
}
view raw package.json hosted with ❤ by GitHub

Steps to follow if npm legacy peer deeps problem occurred:

npm install --save --legacy-peer-deps
npm config set legacy-peer-deps true
npm i --legacy-peer-deps
npm config set legacy-peer-deps true
npm cache clean --force
view raw npm_legacy hosted with ❤ by GitHub

This is how the folder structure will look in Appium with the WebDriverIO Framework:

Fig:- Appium Framework Outline

Step-by-Step Configuration of Android Emulator using Android Studio

Fig:- Android Studio Launch


Fig:- Android Studio AVD Manager


Fig:- Create Virtual Device


Fig:- Choose a device Definition


Fig:- Select system image

Fig:- License Agreement

 

Fig:- Component Installer


Fig:- System Image Download


Fig:- Configuration Verification


Fig:- Virtual Device Listing

Appium Desktop Configuration

Fig:- Appium Desktop Launch

Setup of ANDROID_HOME + ANDROID_SDK_ROOT &  JAVA_HOME

Follow these steps for setting up ANDROID_HOME: 

vi ~/.bash_profile
Add following
export ANDROID_HOME=/Users/pushkar/android-sdk
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/emulator
Save ~/.bash_profile
source ~/.bash_profile
echo $ANDROID_HOME
/Users/pushkar/Library/Android/sdk
view raw android_home hosted with ❤ by GitHub

Follow these steps for setting up ANDROID_SDK_ROOT:

vi ~/.bash_profile
Add following
export ANDROID_HOME=/Users/pushkar/Android/sdk
export ANDROID_SDK_ROOT=/Users/pushkar/Android/sdk
export ANDROID_AVD_HOME=/Users/pushkar/.android/avd
Save ~/.bash_profile
source ~/.bash_profile
echo $ANDROID_SDK_ROOT
/Users/pushkar/Library/Android/sdk

Follow these steps for setting up JAVA_HOME:

java --version
vi ~/.bash_profile
Add following
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-16.0.1.jdk/Contents/Home.
echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk-16.0.1.jdk/Contents/Home
view raw java_home hosted with ❤ by GitHub

Fig:- Environment Variables in Appium


Fig:- Appium Server Starts 


Fig:- Appium Start Inspector Session

Fig:- Inspector Session Configurations

Note - Make sure you need to install the app from Google Play Store. 

Fig:- Android Emulator Launch  


Fig: - Android Emulator with Facebook React Native Mobile App


Fig:- Success of Appium with Emulator

 

Fig:- Locating Elements using Appium Inspector

How to write E2E React Native Mobile App Tests 

Fig:- Test Suite Structure of Mocha

Here is an example of how to write E2E test in Appium:

Positive Testing Scenario - Validate Login & Nav Bar

  1. Open Facebook React Native App 
  2. Enter valid email and password
  3. Click on Login
  4. Users should be able to login into Facebook 

Negative Testing Scenario - Invalid Login

  1. Open Facebook React Native App
  2. Enter invalid email and password 
  3. Click on login 
  4. Users should not be able to login after receiving an “Incorrect Password” message popup

Negative Testing Scenario - Invalid Element

  1. Open Facebook React Native App 
  2. Enter invalid email and  password 
  3. Click on login 
  4. Provide invalid element to capture message

Make sure test_script should be under test/specs folder 

var expect = require('chai').expect
beforeEach(() => {
driver.launchApp()
})
afterEach(() => {
driver.closeApp()
})
describe('Verify Login Scenarios on Facebook React Native Mobile App', () => {
it('User should be able to login using valid credentials to Facebook Mobile App', () => {
$(`~Username`).waitForDisplayed(20000)
$(`~Username`).setValue('Valid-Email')
$(`~Password`).waitForDisplayed(20000)
$(`~Password`).setValue('Valid-Password')
$('~Log In').click()
browser.pause(10000)
})
it('User should not be able to login with invalid credentials to Facebook Mobile App', () => {
$(`~Username`).waitForDisplayed(20000)
$(`~Username`).setValue('Invalid-Email')
$(`~Password`).waitForDisplayed(20000)
$(`~Password`).setValue('Invalid-Password')
$('~Log In').click()
$(
'//android.widget.TextView[@resource-id="com.facebook.katana:id/(name removed)"]'
)
.waitForDisplayed(11000)
const status = $(
'//android.widget.TextView[@resource-id="com.facebook.katana:id/(name removed)"]'
).getText()
expect(status).to.equal(
`You Can't Use This Feature Right Now`
)
})
it('Test Case should Fail Because of Invalid Element', () => {
$(`~Username`).waitForDisplayed(20000)
$(`~Username`).setValue('Invalid-Email')
$(`~Password`).waitForDisplayed(20000)
$(`~Password`).setValue('Invalid-Pasword')
$('~Log In').click()
$(
'//android.widget.TextView[@resource-id="com.facebook.katana:id/(name removed)"'
)
.waitForDisplayed(11000)
const status = $(
'//android.widget.TextView[@resource-id="com.facebook.katana"'
).getText()
expect(status).to.equal(
`You Can't Use This Feature Right Now`
)
})
})
view raw e2e_test.js hosted with ❤ by GitHub

How to Run Mobile Tests Scripts  

$ npm test
This will create a Results folder with .xml report
view raw run_test hosted with ❤ by GitHub

Reporting

The following are examples of the supported reporters:

  • Allure Reporter
  • Concise Reporter
  • Dot Reporter
  • JUnit Reporter
  • Spec Reporter
  • Sumologic Reporter
  • Report Portal Reporter
  • Video Reporter
  • HTML Reporter
  • JSON Reporter
  • Mochawesome Reporter
  • Timeline Reporter
  • CucumberJS JSON Reporter

Here, we are using Allure Reporting. Allure Reporting in WebdriverIO is a plugin to create Allure Test Reports.

The easiest way is to keep @wdio/allure-reporter as a devDependency in your package.json with

$ npm install @wdio/allure-reporter --save-dev
view raw package.sh hosted with ❤ by GitHub

Reporter options can be specified in the wdio.conf.js configuration file 

reporters: [
[
'allure',
{
outputDir: 'allure-results',
disableWebdriverStepsReporting: true,
disableWebdriverScreenshotsReporting: false
}
]
]
view raw wdio.conf.js hosted with ❤ by GitHub

To convert Allure .xml report to .html report, run the following command: 

$ allure generate && allure open
Allure HTML report should be opened in browser

This is what Allure Reports look like: 

Fig:- Allure Report Overview 


Fig:- Allure Categories


Fig:- Allure Suites


Fig: - Allure Graphs


Fig:- Allure Timeline


Fig:- Allure Behaviors


Fig:- Allure Packages

Limitations with Appium & WebDriverIO

Appium 

  • Android versions lower than 4.2 are not supported for testing
  • Limited support for hybrid app testing
  • Doesn't support image comparison.

WebdriverIO

  • It has a custom implementation
  • It can be used for automating AngularJS apps, but it is not as customized as Protractor.

Conclusion

In the QA and developer ecosystem, using Appium to test React native applications is common. Appium makes it easy to record test cases on both Android and iOS platforms while working with React Native. Selenium, a basic web developer, acts as a bridge between Appium and mobile platforms for delivery and testing. Appium is a solid framework for automatic UI testing. This article explains that this framework is capable of conducting test cases quickly and reliably. Most importantly, it can test both Android and iOS apps developed by the React Native framework on the basis of a single code.

Related Articles -

References 

Get the latest engineering blogs delivered straight to your inbox.
No spam. Only expert insights.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings

Test Automation in React Native apps using Appium and WebdriverIO

React Native provides a mobile app development experience without sacrificing user experience or visual performance. And when it comes to mobile app UI testing, Appium is a great way to test indigenous React Native apps out of the box. Creating native apps from the same code and being able to do it using JavaScript has made Appium popular. Apart from this, businesses are attracted by the fact that they can save a lot of money by using this application development framework.

In this blog, we are going to cover how to add automated tests for React native apps using Appium & WebdriverIO with a Node.js framework. 

What are React Native Apps

React Native is an open-source framework for building Android and iOS apps using React and local app capabilities. With React Native, you can use JavaScript to access the APIs on your platform and define the look and behavior of your UI using React components: lots of usable, non-compact code. In the development of Android and iOS apps, “viewing” is the basic building block of a UI: this small rectangular object on the screen can be used to display text, photos, or user input. Even the smallest detail of an app, such as a text line or a button, is a kind of view. Some views may contain other views.

What is Appium

Appium is an open-source tool for traditional automation, web, and hybrid apps on iOS, Android, and Windows desktop mobile platforms. Indigenous apps are those written using iOS and Android. Mobile web applications are accessed using a mobile browser (Appium supports Safari for iOS apps and Chrome or the built-in 'Browser' for Android apps). Hybrid apps have a wrapper around "web view"—a traditional controller that allows you to interact with web content. Projects like Apache Cordova make it easy to build applications using web technology and integrate it into a traditional wrapper, creating a hybrid application.

Importantly, Appium is "cross-platform", allowing you to write tests against multiple platforms (iOS, Android), using the same API. This enables code usage between iOS, Android, and Windows test suites. It runs on iOS and Android applications using the WebDriver protocol.

Fig:- Appium Architecture

What is WebDriverIO

WebdriverIO is a next-gen browser and Node.js automated mobile testing framework. It allows you to customize any application written with modern web frameworks for mobile devices or browsers, such as React, Angular, Polymeror, and Vue.js.

WebdriverIO is a widely used test automation framework in JavaScript. It has various features like it supports many reports and services, Test Frameworks, and WDIO CLI Test Runners

The following are examples of supported services:

  • Appium Service
  • Devtools Service
  • Firefox Profile Service
  • Selenium Standalone Service
  • Shared Store Service
  • Static Server Service
  • ChromeDriver Service
  • Report Portal Service
  • Docker Service

The followings are supported by the test framework:

  • Mocha
  • Jasmine
  • Cucumber 
Fig:- WebdriverIO Architecture

Key features of Appium & WebdriverIO

Appium

  • Does not require application source code or library
  • Provides a strong and active community
  • Has multi-platform support, i.e., it can run the same test cases on multiple platforms
  • Allows the parallel execution of test scripts
  • In Appium, a small change does not require reinstallation of the application
  • Supports various languages like C#, Python, Java, Ruby, PHP, JavaScript with node.js, and many others that have a Selenium client library

WebdriverIO 

  • Extendable
  • Compatible
  • Feature-rich 
  • Supports modern web and mobile frameworks
  • Runs automation tests both for web applications as well as native mobile apps.
  • Simple and easy syntax
  • Integrates tests to third-party tools such as Appium
  • 'Wdio setup wizard' makes the setup simple and easy
  • Integrated test runner

Installation & Configuration

$ mkdir Demo_Appium_Project

  • Create a sample Appium Project

$ npm init
$ package name: (demo_appium_project) demo_appium_test
$ version: (1.0.0) 1.0.0
$ description: demo_appium_practice
$ entry point: (index.js) index.js
$ test command: "./node_modules/.bin/wdio wdio.conf.js"
$ git repository:
$ keywords:
$ author: Pushkar
$ license: (ISC) ISC

This will also create a package.json file for test settings and project dependencies.

  • Install node packages

$ npm install
view raw node_package hosted with ❤ by GitHub

  • Install Appium through npm or as a standalone app.

$ npm install -g appium or npm install --save appium
view raw install_appium hosted with ❤ by GitHub

  • Install WebdriverIO

$ npm install -g webdriverio or npm install --save-dev webdriverio @wdio/cli

  • Install Chai Assertion library 

$ npm install -g chai or npm install --save chai
view raw install_chai hosted with ❤ by GitHub

Make sure you have following versions installed: 

$ node --version - v.14.17.0
$ npm --version - 7.17.0
$ appium --version - 1.21.0
$ java --version - java 16.0.1
$ allure --version - 2.14.0

WebdriverIO Configuration 

The web driver configuration file must be created to apply the configuration during the test Generate command below project:

$ npx wdio config
view raw wdio_config hosted with ❤ by GitHub

With the following series of questions, install the required dependencies,

$ Where is your automation backend located? - On my local machine
$ Which framework do you want to use? - mocha
$ Do you want to use a compiler? No!
$ Where are your test specs located? - ./test/specs/**/*.js
$ Do you want WebdriverIO to autogenerate some test files? - Yes
$ Do you want to use page objects (https://martinfowler.com/bliki/PageObject.html)? - No
$ Which reporter do you want to use? - Allure
$ Do you want to add a service to your test setup? - No
$ What is the base url? - http://localhost
view raw wdio_config hosted with ❤ by GitHub

This is how wdio.conf.js looks:

exports.config = {
port: 4724,
path: '/wd/hub/',
runner: 'local',
specs: ['./test/specs/*.js'],
maxInstances: 1,
capabilities: [
{
platformName: 'Android',
platformVersion: '11',
appPackage: 'com.facebook.katana',
appActivity: 'com.facebook.katana.LoginActivity',
automationName: 'UiAutomator2'
}
],
services: [
[
'appium',
{
args: {
relaxedSecurity: true
},
command: 'appium'
}
]
],
logLevel: 'debug',
bail: 0,
baseUrl: 'http://localhost',
waitforTimeout: 10000,
connectionRetryTimeout: 90000,
connectionRetryCount: 3,
framework: 'mocha',
reporters: [
[
'allure',
{
outputDir: 'allure-results',
disableWebdriverStepsReporting: true,
disableWebdriverScreenshotsReporting: false
}
]
],
mochaOpts: {
ui: 'bdd',
timeout: 60000
},
afterTest: function(test, context, { error, result, duration, passed, retries }) {
if (!passed) {
browser.takeScreenshot();
}
}
}
view raw wdio.conf.js hosted with ❤ by GitHub

For iOS Automation, just add the following capabilities in wdio.conf.js & the Appium Configuration: 

{
"platformName": "IOS",
"platformVersion": "14.5",
"app": "/Your_PATH/wdioNativeDemoApp.app",
"deviceName": "iPhone 12 Pro Max"
}
view raw ios.conf.js hosted with ❤ by GitHub

Launch the iOS Simulator from Xcode

Install Appium Doctor for iOS by using following command:

npm install -g appium-doctor

Fig:- Appium Doctor Installed

This is how package.json will look:

{
"name": "demo_appium_test",
"version": "1.0.0",
"description": "demo_appium_practice",
"main": "index.js",
"scripts": {
"test": "./node_modules/.bin/wdio wdio.conf.js"
},
"author": "Pushkar",
"license": "ISC",
"dependencies": {
"@wdio/sync": "^7.7.4",
"appium": "^1.21.0",
"chai": "^4.3.4",
"webdriverio": "^7.7.4"
},
"devDependencies": {
"@wdio/allure-reporter": "^7.7.3",
"@wdio/appium-service": "^7.7.3",
"@wdio/cli": "^7.7.4",
"@wdio/local-runner": "^7.7.4",
"@wdio/mocha-framework": "^7.7.4",
"@wdio/selenium-standalone-service": "^7.7.4"
}
}
view raw package.json hosted with ❤ by GitHub

Steps to follow if npm legacy peer deeps problem occurred:

npm install --save --legacy-peer-deps
npm config set legacy-peer-deps true
npm i --legacy-peer-deps
npm config set legacy-peer-deps true
npm cache clean --force
view raw npm_legacy hosted with ❤ by GitHub

This is how the folder structure will look in Appium with the WebDriverIO Framework:

Fig:- Appium Framework Outline

Step-by-Step Configuration of Android Emulator using Android Studio

Fig:- Android Studio Launch


Fig:- Android Studio AVD Manager


Fig:- Create Virtual Device


Fig:- Choose a device Definition


Fig:- Select system image

Fig:- License Agreement

 

Fig:- Component Installer


Fig:- System Image Download


Fig:- Configuration Verification


Fig:- Virtual Device Listing

Appium Desktop Configuration

Fig:- Appium Desktop Launch

Setup of ANDROID_HOME + ANDROID_SDK_ROOT &  JAVA_HOME

Follow these steps for setting up ANDROID_HOME: 

vi ~/.bash_profile
Add following
export ANDROID_HOME=/Users/pushkar/android-sdk
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/emulator
Save ~/.bash_profile
source ~/.bash_profile
echo $ANDROID_HOME
/Users/pushkar/Library/Android/sdk
view raw android_home hosted with ❤ by GitHub

Follow these steps for setting up ANDROID_SDK_ROOT:

vi ~/.bash_profile
Add following
export ANDROID_HOME=/Users/pushkar/Android/sdk
export ANDROID_SDK_ROOT=/Users/pushkar/Android/sdk
export ANDROID_AVD_HOME=/Users/pushkar/.android/avd
Save ~/.bash_profile
source ~/.bash_profile
echo $ANDROID_SDK_ROOT
/Users/pushkar/Library/Android/sdk

Follow these steps for setting up JAVA_HOME:

java --version
vi ~/.bash_profile
Add following
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-16.0.1.jdk/Contents/Home.
echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk-16.0.1.jdk/Contents/Home
view raw java_home hosted with ❤ by GitHub

Fig:- Environment Variables in Appium


Fig:- Appium Server Starts 


Fig:- Appium Start Inspector Session

Fig:- Inspector Session Configurations

Note - Make sure you need to install the app from Google Play Store. 

Fig:- Android Emulator Launch  


Fig: - Android Emulator with Facebook React Native Mobile App


Fig:- Success of Appium with Emulator

 

Fig:- Locating Elements using Appium Inspector

How to write E2E React Native Mobile App Tests 

Fig:- Test Suite Structure of Mocha

Here is an example of how to write E2E test in Appium:

Positive Testing Scenario - Validate Login & Nav Bar

  1. Open Facebook React Native App 
  2. Enter valid email and password
  3. Click on Login
  4. Users should be able to login into Facebook 

Negative Testing Scenario - Invalid Login

  1. Open Facebook React Native App
  2. Enter invalid email and password 
  3. Click on login 
  4. Users should not be able to login after receiving an “Incorrect Password” message popup

Negative Testing Scenario - Invalid Element

  1. Open Facebook React Native App 
  2. Enter invalid email and  password 
  3. Click on login 
  4. Provide invalid element to capture message

Make sure test_script should be under test/specs folder 

var expect = require('chai').expect
beforeEach(() => {
driver.launchApp()
})
afterEach(() => {
driver.closeApp()
})
describe('Verify Login Scenarios on Facebook React Native Mobile App', () => {
it('User should be able to login using valid credentials to Facebook Mobile App', () => {
$(`~Username`).waitForDisplayed(20000)
$(`~Username`).setValue('Valid-Email')
$(`~Password`).waitForDisplayed(20000)
$(`~Password`).setValue('Valid-Password')
$('~Log In').click()
browser.pause(10000)
})
it('User should not be able to login with invalid credentials to Facebook Mobile App', () => {
$(`~Username`).waitForDisplayed(20000)
$(`~Username`).setValue('Invalid-Email')
$(`~Password`).waitForDisplayed(20000)
$(`~Password`).setValue('Invalid-Password')
$('~Log In').click()
$(
'//android.widget.TextView[@resource-id="com.facebook.katana:id/(name removed)"]'
)
.waitForDisplayed(11000)
const status = $(
'//android.widget.TextView[@resource-id="com.facebook.katana:id/(name removed)"]'
).getText()
expect(status).to.equal(
`You Can't Use This Feature Right Now`
)
})
it('Test Case should Fail Because of Invalid Element', () => {
$(`~Username`).waitForDisplayed(20000)
$(`~Username`).setValue('Invalid-Email')
$(`~Password`).waitForDisplayed(20000)
$(`~Password`).setValue('Invalid-Pasword')
$('~Log In').click()
$(
'//android.widget.TextView[@resource-id="com.facebook.katana:id/(name removed)"'
)
.waitForDisplayed(11000)
const status = $(
'//android.widget.TextView[@resource-id="com.facebook.katana"'
).getText()
expect(status).to.equal(
`You Can't Use This Feature Right Now`
)
})
})
view raw e2e_test.js hosted with ❤ by GitHub

How to Run Mobile Tests Scripts  

$ npm test
This will create a Results folder with .xml report
view raw run_test hosted with ❤ by GitHub

Reporting

The following are examples of the supported reporters:

  • Allure Reporter
  • Concise Reporter
  • Dot Reporter
  • JUnit Reporter
  • Spec Reporter
  • Sumologic Reporter
  • Report Portal Reporter
  • Video Reporter
  • HTML Reporter
  • JSON Reporter
  • Mochawesome Reporter
  • Timeline Reporter
  • CucumberJS JSON Reporter

Here, we are using Allure Reporting. Allure Reporting in WebdriverIO is a plugin to create Allure Test Reports.

The easiest way is to keep @wdio/allure-reporter as a devDependency in your package.json with

$ npm install @wdio/allure-reporter --save-dev
view raw package.sh hosted with ❤ by GitHub

Reporter options can be specified in the wdio.conf.js configuration file 

reporters: [
[
'allure',
{
outputDir: 'allure-results',
disableWebdriverStepsReporting: true,
disableWebdriverScreenshotsReporting: false
}
]
]
view raw wdio.conf.js hosted with ❤ by GitHub

To convert Allure .xml report to .html report, run the following command: 

$ allure generate && allure open
Allure HTML report should be opened in browser

This is what Allure Reports look like: 

Fig:- Allure Report Overview 


Fig:- Allure Categories


Fig:- Allure Suites


Fig: - Allure Graphs


Fig:- Allure Timeline


Fig:- Allure Behaviors


Fig:- Allure Packages

Limitations with Appium & WebDriverIO

Appium 

  • Android versions lower than 4.2 are not supported for testing
  • Limited support for hybrid app testing
  • Doesn't support image comparison.

WebdriverIO

  • It has a custom implementation
  • It can be used for automating AngularJS apps, but it is not as customized as Protractor.

Conclusion

In the QA and developer ecosystem, using Appium to test React native applications is common. Appium makes it easy to record test cases on both Android and iOS platforms while working with React Native. Selenium, a basic web developer, acts as a bridge between Appium and mobile platforms for delivery and testing. Appium is a solid framework for automatic UI testing. This article explains that this framework is capable of conducting test cases quickly and reliably. Most importantly, it can test both Android and iOS apps developed by the React Native framework on the basis of a single code.

Related Articles -

References 

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings