Eze Sunday Eze Sunday is a full-stack software developer and technical writer passionate about solving problems, one line of code at a time. Currently building Raveshift.com, a crypto exchange and tools for crypto payment solutions.

Testing your React Native app with Appium

4 min read 1353

Appium Logo

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.

Prerequisites

  • You should have Node.js installed
  • A basic knowledge of mobile app development with React Native will be helpful

What is 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.

Appium Architecture
Appium architecture

Setting up your React Native app

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.

Installation

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:

We made a custom demo for .
No really. Click here to check it out.

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:

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.

Installing Appium in React Native

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);
});

Running the test in Appium

To run the test, we first start the Appium server by running Appium on the command line, like so:

[email protected] 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.

Conclusion

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!

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.
Eze Sunday Eze Sunday is a full-stack software developer and technical writer passionate about solving problems, one line of code at a time. Currently building Raveshift.com, a crypto exchange and tools for crypto payment solutions.

Leave a Reply