When it comes to building apps, software testing is critical. According to a recent report by the Consortium for Information and Software Quality, poor software quality cost organizations across all U.S. sectors over $2.08 trillion in 2020.
As a software developer, building a solid, well-tested application will set you apart from the crowd by improving user — and developer — satisfaction.
So, let’s learn how to test React Native mobile applications with Appium.
Appium is a cross-platform automated testing tool for native, hybrid, and mobile web applications. It supports iOS, Android, and Windows UI testing.
How does it work, you ask?
Appium has a client-server architecture. The Appium client sends a request to the Appium server (a Node.js HTTP server) and, in turn, the Appium server sends a request to the device where the action is performed. Then, the server returns the result to the client to let you know the status of the test.
Let’s set up a basic React Native application with a login screen and test some of the UI elements.
We’ll use the Expo command-line tool to build and run the sample React Native application we’ll create.
Run the command below to install Expo CLI on your machine:
npm install --global expo-cli
Next, run this command to create a starting point for your React Native application:
expo init my-app # my-app is your app's name. So, you can change it to whatever name you want.
When you run the above command, you’ll be prompted with a few boilerplate template options to choose from. For example:
? Choose a template: › - Use arrow-keys. Return to submit. ----- Managed workflow ----- blank a minimal app as clean as an empty canvas blank (TypeScript) same as blank but with TypeScript configuration tabs (TypeScript) several example screens and tabs using react-navigation and TypeScript ----- Bare workflow ----- ❯ minimal bare and minimal, just the essentials to get you started minimal (TypeScript) same as minimal but with TypeScript configuration
For this tutorial, use the arrow key to choose the minimal installation option. Then wait for the installation to complete. It should take about a minute or more, depending on your internet connection strength.
When that’s done, run cd my-app
. Now your app is ready. Open the App.js
file so we can modify it. Add the code below for the login page.
import React, { useState } from 'react'; import { StyleSheet, Text, View, TextInput, TouchableOpacity } from 'react-native'; const App = () => { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); return ( <View style={styles.container}> <Text style={styles.logo}>Login</Text> <View style={styles.inputView} > <TextInput style={styles.inputText} placeholder="Email..." placeholderTextColor="#003f5c" onChangeText={text => setEmail(text)} /> </View> <View style={styles.inputView} > <TextInput secureTextEntry style={styles.inputText} placeholder="Password..." placeholderTextColor="#003f5c" onChangeText={text => setPassword(text)} /> </View> <TouchableOpacity> <Text style={styles.forgot}>Forgot Password?</Text> </TouchableOpacity> <TouchableOpacity style={styles.loginBtn}> <Text style={styles.loginText}>LOGIN</Text> </TouchableOpacity> <TouchableOpacity> <Text style={styles.loginText}>Signup</Text> </TouchableOpacity> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#003f5c', alignItems: 'center', justifyContent: 'center', }, logo: { fontWeight: "bold", fontSize: 50, color: "#3CB371", marginBottom: 40 }, inputView: { width: "80%", backgroundColor: "#465881", borderRadius: 25, height: 50, marginBottom: 20, justifyContent: "center", padding: 20 }, inputText: { height: 50, color: "white" }, forgot: { color: "white", fontSize: 11 }, loginBtn: { width: "80%", backgroundColor: "#3CB371", borderRadius: 25, height: 50, alignItems: "center", justifyContent: "center", marginTop: 40, marginBottom: 10 }, loginText: { color: "white" } }); export default App;
Run expo start
and choose the device you want to run your app on. I will be using the iOS 11 emulator (You can use your Android or iOS phone). If you run that, you should see this login page:
Now the app is set up, but there is something important to note. Because Appium’s element-finding algorithm works with the UI accessibility layer, you’ll need to add a UI accessibility label instead of accessing the UI elements by their ID for Appium in order to test them. So, we’ll add this layer to our existing components, like so:
<TextInput style={styles.inputText} placeholder="Email..." placeholderTextColor="#003f5c" accessibilityLabel="email" onChangeText={text => setEmail(text)} /> </View>
Great! Now let’s set up Appium and run our test.
There are two ways to install the Appium server. You can download and install Appium desktop or install it with npm.
If you are going to install it via npm, then run npm install -g appium
, which is the pattern we’ll use in this tutorial.
After that, install the WD.js web driver we’ll use to communicate with the Appium server.
npm install wd
To ensure that everything looks good, you can install appium-doctor with npm.
npm install appium-doctor -g
Then run it on your Terminal:
appium-doctor -h
Next, create a test file and add the following code to it:
import wd from 'wd'; jasmine.DEFAULT_TIMEOUT_INTERVAL = 600000; const PORT = 4723; const config = { platformName: "iOS", platformVersion: "14.4", deviceName: "iPhone 11", app: "path/to/your.apk or yourapp.ipa", automationName: "XCUITest",// UiAutomator2, Espresso, or UiAutomator1 for Android }; const driver = wd.promiseChainRemote('localhost', PORT); beforeAll(async () => { await driver.init(config); }) test('Test Accessibilty Id', async () => { expect(await driver.hasElementByAccessibilityId('email')).toBe(true); expect(await driver.hasElementByAccessibilityId('password')).toBe(true); });
The config part is important, so make sure you enter the right options for your device (iOS device config).
const config = { platformName: "iOS", platformVersion: "14.4", deviceName: "iPhone 11", app: "path/to/your.apk or yourapp.ipa", automationName: "XCUITest",// UiAutomator2, Espresso, or UiAutomator1 for Android };
A configuration for an Android device should look like this, for example:
const config = { platformName: "Android", platformVersion: "8", deviceName: "Android Emulator", app: "/path/to/the/downloaded/app.apk", automationName: "UiAutomator2" }
And here, we have the driver setup.
const driver = wd.promiseChainRemote('localhost', PORT);
Now we need to configure the web driver and set the remote server and the port. In our case, Appium is running on our local machine, so we set it as localhost
and we use the default port 4723
.
Now begins testing. Here, we are just confirming that the accessibility label is set for the email and password fields. This is what it should look like.
test('Test Accessibilty Id', async () => { expect(await driver.hasElementByAccessibilityId('email')).toBe(true); expect(await driver.hasElementByAccessibilityId('password')).toBe(true); });
To run the test, we first start the Appium server by running Appium on the command line, like so:
ezesundayeze@Ezes-MacBook-Pro appium-app $ appium [Appium] Welcome to Appium v1.20.2 [Appium] Appium REST http interface listener started on 0.0.0.0:4723
Next, open another terminal and run npm test login
. Your result should look like this:
Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 1 total Time: 5.775s, estimated 7s Ran all test suites matching /login/i.
Appium will go over the app UI and test that the accessibility labels are being set for email and password. If all is good it returns a pass, otherwise, your test fails.
That’s it! You’re done.
There are other options you could use aside from Appium, like Selenium or Selendroid, for example. However, Appium is the most popular mobile automation testing tool because Appium’s test can be written for both iOS and Android using the same API, and it’s open-source.
Testing your React Native mobile app can be time-consuming, but it’s a critical investment for your future self and the team that manages the application because it prevents bugs, improves customer’s confidence and loyalty, and allows you to sleep well at night.
Hopefully, you’ve learned the importance of testing your application and how to get started testing your mobile app using Appium.
As always, check out the Appium docs to take a deeper dive into testing your React Native app. Happy coding!
LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.
Start proactively monitoring your React Native apps — try LogRocket for free.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowCompare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.