?

In This White Paper

In this article, we are going to see how to use Appium to automate a React-Native Android mobile application by writing an example test, but let's first walk through an overview of Appium and a few use cases.

copy link

What is Appium?

It's an open-source Mobile User Interface (UI) automation tool for testing native apps (Android & iOS) and mobile browsers. Appium has become almost synonymous with mobile test automation, as it's the most popular tool for testing mobile apps.

Appium internally uses WebDriver JSON Wire protocol (Which Selenium does) to test the Apps. So, it is just like selenium but for Mobile.

copy link

Why use Appium for mobile automation?

  1. It's open-source mobile automation.
  2. Tools like Robotium only work on a single mobile platform (such as Android in this case).
  3. One more tool called Selenium Android works only for Android.
  4. There is one more tool called kalabash which works for iOS.
  5. Appium is the only testing tool that runs on both Android and iOS.
  6. Appium works on both
    1. Native apps: exclusively developed on Android or iOS.
    2. Hybrid apps: website code packaged into containers to emulate the appearance and behavior of native apps. They are platform agnostic.
  7. Appium utilizes a version of Selenium's JSON Wire protocol. That means it supports all the API calls that the web driver supports but in mobile testing.

Supported platforms: iOS, Android, Firefox OS.

Supported languages: We can write Appium code in any language supported by the web driver (Java, C#, JavaScript, Python, Ruby, etc.).

copy link

Appium architecture

Appium Architecture

The UiAutomator2 is an automation framework used when writing tests for Android apps.

In the same way, the XCUITest is for the iOS platform.

The Appium tool uses these automation frameworks under the hood to perform automation on their platforms. There are alternatives but they are more challenging. These frameworks make it easier

Advantages:

  • Support for multiple languages and tools
  • Cross-platform test cases
  • Similarity with Selenium
  • Integration with CI tools.
  • It is free and open-source.

Disadvantages:

  • Speed (tests can be slow to execute)
  • Flaky tests
  • Difficult to setup
  • No support for older Android Versions. (< 4.2)

Intended course audience

The target audience for this course includes:

  • Automation testers
  • Automation developers

copy link

Initial setup

To get started, we need to complete the below installations on Mac OS:

  1. Initial Android installation.
  2. Install Appium
  3. Install Node.js
  4. Starting Appium server

1. Initial Android installation

  1. Download and Install JDK 1.8 on the machine.
  2. ​Configure the JAVA_HOME environment variable to point to the location you installed JDK 1.8, in your .profile file.
  3. Download ANDROID STUDIO  - https://developer.android.com/studio/
  4. Start Android studio to set up and initialize Android SDK
  5. Do the ​environment variable setup for​ ANDROID_HOME
  6. Open AVD Manager and create a new virtual device.

After creating a virtual device, start/run the created virtual device Go to the terminal and type "adb devices" and make sure you see your device id as below :

Terminal with a list of devices attached

2. Install Appium

 Download the Appium server from: http://appium.io/ 

Download the Appium server from the highlighted

 

3. Install Node.js from https://nodejs.org/en/download/

4. Starting Appium server

  • Through Terminal:  Open the terminal and type > npm install -g appium
  •  Through Appium App, click on Start Server as shown below:
Start Appium server manually

copy link

Create a simple project

We can create the project in any IDE of our choice. In this example, I have used IntelliJ and chose the project type as MavenThe framework followed is POM (Page Object Model) with TestNG. The language chosen is Java for coding.

POM - In the Page Object Model design pattern, we create a class for each web page. This class consists of different Android elements present on each page as shown below from the project structure. The folder is named "PageObjects."

Why POM?

  • Makes code maintainable.
  • Makes code readable.
  • Makes code reusable.
Page Objects

Maven - It is a build automation tool used primarily for Java projects. It is very helpful for a project while updating the central repository of JARs and other dependencies. Pom(Project Object Model).xml is an XML file that contains information about the project and configuration details used by Maven to build the project.

Pom.xml – All the version dependencies that are needed for the project are added in the pom.xml file. As soon as we add the dependency, respective libraries get downloaded into the project. 

pom.xml displays the version dependencies

TestNG – It is a testing framework for the Java programming language inspired by JUnit and NUnit. It covers a wider range of test categories: unit, functional, end-to-end, integration, etc.

testng.xml is a file that contains the test configuration and it allows us to organize test classes and define test suites and tests. Execution of test suit starts from testng.xml file.

copy link

How to write a simple test scenario

Scenario: A user adds a few items to their cart and later changed their mind to reset the cart and start from the beginning. With the help of the start over button, the user can reset their orders all at once. 

Here the test case is to add items to the cart and validate the start over button functionality on the My Cart screen. 

 

Android emulator displaying START OVER button

MyOrdersPage.java (implemented using Page Object design pattern):

Below are the xpaths of all android elements that are present on the My orders screen which have been combined together under a single class MyOrdersPage.java as shown below :

package pageObjects;

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.pagefactory.AndroidFindBy;
import io.appium.java_client.pagefactory.AppiumFieldDecorator;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.PageFactory;

public class MyOrdersPage {
    public MyOrdersPage(AppiumDriver driver)
    {
        PageFactory.initElements(new AppiumFieldDecorator(driver),this);
    }

    @AndroidFindBy(xpath="//android.widget.TextView[@text='CHECKOUT']")
    public WebElement Checkout;

    @AndroidFindBy(xpath="//android.view.ViewGroup[@index='1']")
    public WebElement decrQty;

    @AndroidFindBy(xpath="//android.widget.TextView[@text='PICKUP ORDER']")
    public WebElement PickupOrder;

    @AndroidFindBy(xpath="//android.widget.TextView[@text='START OVER']")
    public WebElement StartOver;

PageFactory.initElements - PageFactory is a class provided by Selenium WebDriver to support Page Object Design patterns. The initElements method is used to initialize web elements.

With the help of the UiAutomatorviewer tool, we identify the XPaths of every element present on the screen.

copy link

How to open the UiAutomatorviewer tool

  • Open a new terminal, and switch to JDK 1.8 version if you are on a different version by default (explained further in the Challenges section at the bottom of the article).
  • Type "uiautomatorviewer" in the same terminal.
Commands to switch to JDK 1.8 and to open uiAutomatorviewer

Note: The UiAutomatorviewer executable is found under ${HOME}/Library/Android/sdk/tools/bin

path of uiautomatorviewer.exec

copy link

How to inspect/spy on the element on the UiAutomatorviewer

In the above screenshot, on the left side is the virtual device, and on the right is Uiautomatorviewer. Uiautomatorviewer has taken a screenshot of the virtual device's screen. Inspecting the Android element allows the Xpath of the element to be accessed.

Syntax: @AndroidFindBy(xpath="//className[@Attribute='Value']")

Example:@AndroidFindBy(xpath="//android.widget.TextView[@text='START OVER']")

 public WebElement StartOver;

The above MyOrdersPage.java class is called in the below test class which is highlighted in yellow.ValidateStartOverButton.java - This is a test class that consists of the automation code to reach the Start Over button on the My Orders screen.

HimalayaCreameryBase class:

The test class extends to HimalayaCreameryBase class which consists of common methods such as StartServer(), GetScreenshot(), Capabilities(). In this method, we define the desired capabilities of the Android device and the server port to which the Android Driver has to communicate with the client code.

package Test;

import CommonCode.HimalayaCreameryBase;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
import org.testng.annotations.AfterTest;
import org.testng.annotations.Test;
import pageObjects.*;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class ValidateStartOverButton extends HimalayaCreameryBase {
    String AppName = "app-debug.apk";
    public AndroidDriver<AndroidElement> driver;

    @Test
    public void StartOverCart() throws IOException, InterruptedException {
        service = startserver();					
        driver = Capabilities(AppName);
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        LoginPageAndroid login = new LoginPageAndroid(driver);
        login.ContGuest.click();
        HomePageAndroid homePage = new HomePageAndroid(driver);
        homePage.PickUp.click();
        homePage.whileUsingApp.click();
        StoresPage stores = new StoresPage(driver);
        stores.Store2.click();
        CategoriesPage categories = new CategoriesPage(driver);
        categories.IceCream.click();
        IceCreamPage icecream = new IceCreamPage(driver);
        icecream.Blackberry.click();
        BottombarPage bottombar = new BottombarPage(driver);
        bottombar.MyCart.click();
        MyOrdersPage ordersPage = new MyOrdersPage(driver);
        ordersPage.StartOver.click();
        ordersPage.Yes.click();
    }
   
 @AfterTest
    public void teardown()
    {
        if(driver!=null)
            driver.quit();
    }
}

copy link

Test case execution

If we want to run a single test case, we can run the test class file as shown below.

Run a single test script

copy link

Test results

Test case passed displayed in the console

copy link

How to run tests from Testng.xml

Run the test by right-clicking on the TestNG XML file and selecting Run As => TestNG Suite.

Once the testng.xml file has run, we can see the results in the console.

The screenshot below is an example of testng.xml.

Extent Reports: It is an open-source reporting library useful for interpreting the results of automated test runs. It can be easily integrated with major testing frameworks like TestNG.

copy link

How to integrate Extent Reports into a project

Add Extent Reports version dependency in pom.xml from the link https://mvnrepository.com/artifact/com.aventstack/extentreports and save the project.

Extent Reports version added in pom.xml

As soon as the test execution is complete, a report generates in the Reports folder which we can view in a browser. In the below screenshot, we see multiple test cases have been run and displayed in two views.

List View:

Extent Report in List View

Graphical View: This representation helps the team and other interested parties to get a better idea of the tests that passed and failed.

Graphical view of Extent Report

Challenges:

  1. Uiatomatorviewer will run on java version -v1.8.0_231. If your java installed version is different other than 1.8v, we need to install the specified version and switch between the versions.
  2. Client code looks for the library jars commons-lang3-3.12.0-bin.zip which can be downloaded from the URL below. Otherwise, we end up with the error in the screenshot below: https://stackoverflow.com/questions/59103308/having-an-error-java-lang-classnotfoundexception
Exception screenshot looking for a library

3.   ExtentHtmlReporter libraries will not work if the version dependency is 5.0.0 or above.

4.   Test case execution failed at loginpage obj = new loginpage(driver)

       Solution:

      I changed the Project SDK version to 1.8 in the following places : 

      File -> Project Structure -> Project Settings

      File -> Project Structure -> Module Settings -> Tab: Sources: Language Level

      File -> Project Structure -> Module Settings -> Tab: Dependencies: Module SDK

      File -> Settings -> Compiler -> Java Compiler -> Target bytecode version.

5. Switch to "export JAVA_HOME=$(/usr/libexec/java_home -v1.8.0_231" on the terminal before you run Appium test cases.

Note: While I was affected by these issues, you may not be. I felt it was worth sharing for your awareness.