Introduction to Appium

Monil Joshi
11 min readJul 14, 2023

--

In the previous article I explained about the things we should understand before starting mobile application testing

You can read that article here
Things you should know before start Mobile application Testing.

I have mentioned some of the tool in the end of the article where I mentioned a cross platform, open source mobile automation tool named Appium.

Appium is an open-source tool for automating native, mobile web, and hybrid applications as mentioned above Appium is “cross-platform” i.e. it allows you to write tests against multiple platforms (iOS, Android), using the same API. This enables code reuse between iOS, Android for common operation like sendkeys, click.

Let’s see, what are pre-requisites to start with Appium

  1. Java JDK : You need Java JDK for 2 reasons.
    — If you are writing your test scripts with one of the supported language Java. Then you must have JDK present on your machine. Make sure you have added JAVA_Home in environment variable
    — if you are using language other than Java to write your script then you might need Java to use Android studio to use SDKs for real devices and to create emulators. However, from android 2.2 and hight version, A copy of the latest OpenJDK comes bundled with Android Studio 2.2 and higher, and this is the JDK version we recommend you use for your Android projects. You can refer this link for more details
    https://developer.android.com/studio/intro/studio-config.html. You can download Java JDK from here
  2. IDE: You must have an IDE to write and execute your script. I will be using IntelliJ to write my code. You can download it from here
  3. Node and NPM: You need to install Node and NPM. As Appium is written in node you need node to run it. If you check Appium source code on GitHub, package.json clearly mention which version of Node and NPM version it needs. You can check it here.

4. Android SDK & Studio: If you are using real device for testing then no need to install Android studio. You can download required SDK from here.

5. To work with Android real device,

— Make sure to enable Developer mode and USB debugging on the device. To enable developer mode tap the Build Number option 7 times. You can read it in more details here for different android version. It is recommend to download install Android studio as it will come up with OpenJDK and it will save cost of real device by using Emulator.

— Make sure you set environment variable ANDROID_HOME in which you will provide SDK path. Also add 2 more values in Path variable. One is ANDROID_HOME\tools and ANDROID_HOME\Platform-tools

— This will help you to use adb (android debug bridge).

6. To work with emulators we will to use Android Virtual Device (AVD)Manager in Android Studio. You can create/delete emulator which matches to your requirement.

7. How to create Emulator

  1. Open Android Studio
  2. Click on Tools > Device Manager
  3. Click on Create Device
  4. Select Catagory “Phone”
  5. Select “Pixel 4” as it comes with play store
  6. Click on Next
  7. Select desired API level
  8. API level refers to android version
  9. You might have to download it at the time of device creation
  10. I am selecting API 28 as I want to create emulator with version android 9
  11. Click on Next
  12. Configure device according to your requirement
  13. Click on Finish
  14. Device will get listed on list of devices
  15. Click on Play button under Actions column to launch emulator
  16. PFA screenshots for emulator creation

Once you launch an emulator you can check by hitting command “adb devices” in command prompt. It will return list of connected device with boot status

7. Appium Server and Inspector: Till version 1.21 Appium desktop comes as bundle which consist Appium server and Appium object inspector . But from Appium version 1.22 it comes differently. You can download Appium Server GUI compatible to your OS from here and Appium inspector compatible to your OS from here. By default Appium service will get hosted on port 4723.

Now we will deep dive in Appium. Start with understanding Appium Architecture.

Appium Architecture

Appium is having Server-Client architecture where Client connected to Server to use its service running on some machine. This communication occurs in form of request and response.

Appium client: It is nothing but test scripts where we have added language binding like necessary jars. It communicates with Appium Server using JSON wire Protocol.

JSON wire protocol: It is collection of end points which are exposed using RESTful APIs. You can read about it more here.

Appium Server: Appium server is HTTP server which written in node.js. This server differentiates request come for android and iOS with the help of Desired Capabilities passed.

Desired Capabilities are keys and values encoded in a JSON object, sent by Appium clients to the server when a new automation session is requested. It tells Appium drivers all kinds of important things about execution happens. Each Appium client builds capabilities in a way specific to the client’s language, but at the end of the day, they are sent over to Appium as JSON objects.

Desired Capabilities can be scripted in the WebDriver test or set within the Appium Server GUI (via an Inspector Session)

Here is an example of desired capabilities

{
"platformName": "iOS",
"platformVersion": "11.0",
"deviceName": "iPhone 7",
"automationName": "XCUITest",
"app": "/path/to/my.app"
}

The UI Automator then processes the request and executes the command on a simulator/emulator/real device.

The results of the test session are then communicated to the server and executes the command on a connected device. It could be simulator/emulator/real device.

Once Appium commands executed on device execution results of the tests are communicated to the server and then back to the client system in terms of logs, using the mobile JSON Wire Protocol.

Now we will see How can we install Appium on system. There are 2 ways to install Appium on your machine.

  1. Installation via NPM: To install Appium with NPM, make sure you have node.js version 12+ is installed on your machine. You can confirm hit by command node -v.
    After that hit the command npm install -g appium and you are done with installation. Here -g means global. Pretty simple right? You have just installed Appium server and whenever you have to execute your test case on mobile with this installed Appium server you have to start this server to listen your commands. Hit command appiumave and your appium server starts running and listening at default port 4723

When to use: You can start Appium server using NPM, when you are done inspecting your objects and you simply have to execute your test case. Alternate option to launch Appium server will consume more memory you can start Appium using command prompt.

2. Installation via Desktop app download: You can download complete Appium bundle and use as any other desktop application. It is a graphical way to launch and use Appium server. You can download it from release page. It will download an exe file which you can install as desktop application. Once you install and launch the application, it will run as Appium server on default port. Also you can use same desktop application to locate your object by clicking on Search icon present on top right corner.

In the above screenshot, you can see appium version as well.
at least till Appium version 1.21.0.1. Now you may think why till 1.21.0.1. Why not now? Till Appium version 1.21.0–1 Appium comes as a bundle having Server as well inspector as well. But if you are using 1.22.x version, inspector has moved as separate tool. You can mouse hover on inspect icon and check tool tip. It says “Inspector Moved”. Click on it and you will redirect to appium inspector git repo. If you scroll down a bit till installation section you will find link to download Appium inspector. You can check this link for the same. Download Appium inspector based on your operating system

This is how look Appium Server UI when you start appium service

By default, Appium will listen your commands on port 4723.

Here is Appium Inspector look like

  1. On top it showing Appium server details. By default it is 127.0.0.1 i.e. pointing to localhost and port number 4723
  2. Enter capabilities as per session you want to initiate. Here you can enter each parameter one by one or simply click on pencil icon on extreme right to edit JSON and paste below code
{
"platformName": "android",
"appium:deviceName": "emulator-5554",
"appium:automationName": "Appium",
"appium:platformVersion": "9",
"appium:app": "D:\\APK\\Perfecto App\\artifacts-1634712923705\\PRIVATE\\Learn_Android_With_Source_Code.apk"
}

Make sure you entered correct device details. appium:app is application apk path present on the machine.

Once you add this capability click on “Start Session”. At first you will get an error below

In this case, you need to provide remote path as /wd/hub

wd refers to webdriver and hub refers to Selenium Grid configuration .

Selenium Grid consists of 2 component

  • Selenium Grid Hub known as hub
  • Selenium Grid Node known as node

wd/hub is the part of the URL through which the node communicates with the hub.

Once you provide remote path as /wd/hub and click on Start session. Application will get launched in device and mirror image of device will be reflected in Appium inspector. Keep checking appium logs to get understanding of what is happening behind the scene.

You might have to click on Refresh Source & screenshot option (present 4th from last)

In this automated test case, I am going to automat below flow

  1. Click on first option “Android UI Widgets”
  2. on Next screen click on Play icon of Edit Text
  3. Enter Some text in edit box
  4. Validate the entered text

First we will learn all the objects

You can click on element on mobile image, it will highlight element in image as well as in the DOM structure.

In Appium inspector, once you decided locator type and value, you can validate it right there.

  1. Click on 2nd last option “Search Element”
  2. Select locator strategy
  3. Enter value
  4. Click on Search
  5. It will give you appearance of the element for given locator type and value
  6. So as per screenshot if we check for id locator with value com.tutorials.learn.androidexample:id/example
  7. It returns 13 objects.

So ID is not correct chioce. Try with XPath //android.widget.TextView[@text=’Android UI Widgets’] and you will get unique element.

Similarly locate remaining element on other screens. Now we can start scritping.

  1. Open IntellJ Idea
  2. Create Java — Gradle project
  3. Add below dependecies in build.gradle
implementation group: 'io.appium', name: 'java-client', version: '8.1.1'
testImplementation group: 'org.testng', name: 'testng', version: '7.1.0'

4. We are using TestNG to execute tests
5. Create a class called “HelloAppium.java”
6. Create static object of AndroidDriver class
7. Create setCapabilities() to add capabilities

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("appium:deviceName", "emulator-5554");
capabilities.setCapability("appium:automationName", "Appium");
capabilities.setCapability("appium:platformVersion", "9");
capabilities.setCapability("app", "<apk_Path>/Learn_Android_With_Source_Code.apk");

8. assing androdi driver object to new instance of AndroidDriver with Appium URL and desired capabilities.

androidDriver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"),capabilities);

Here is complete method

@BeforeTest
public void setCapabilities(){
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("appium:deviceName", "emulator-5554");
capabilities.setCapability("appium:automationName", "Appium");
capabilities.setCapability("appium:platformVersion", "9");
capabilities.setCapability("appium:app", "<Apk_Path>/Learn_Android_With_Source_Code.apk");
try {
androidDriver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"),capabilities);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}

9. we are using @BeforeTest annotation for above method
10. Now create test method testUiWidgets using @Test annotation.
11. Add learned objects with action in it

@Test
public void testUiWidgets() throws InterruptedException {
String textPass = "Hello";
Thread.sleep(3000);
androidDriver.findElement(By.xpath("//android.widget.TextView[@text='Android UI Widgets']")).click();
androidDriver.findElement(By.xpath("//android.widget.TextView[@text='EditText']/following-sibling::android.widget.ImageView")).click();
Thread.sleep(2000);
androidDriver.findElement(By.className("android.widget.EditText")).sendKeys(textPass);
String typedText = androidDriver.findElement(By.id("com.tutorials.learn.androidexample:id/txtedt")).getText();
Assert.assertTrue(textPass.equalsIgnoreCase(typedText));
}

12. Add tear down method to shut down appium session

@AfterTest
public void tearDown(){
androidDriver.quit();
}

Here is complete code

public class HelloAppium {
static AndroidDriver androidDriver;

@BeforeTest
public void setCapabilities(){
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("appium:deviceName", "emulator-5554");
capabilities.setCapability("appium:automationName", "Appium");
capabilities.setCapability("appium:platformVersion", "9");
capabilities.setCapability("appium:app", "<APK_Path>/Learn_Android_With_Source_Code.apk");
try {
androidDriver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"),capabilities);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
@Test
public void testUiWidgets() throws InterruptedException {
String textPass = "Hello";
Thread.sleep(3000);
androidDriver.findElement(By.xpath("//android.widget.TextView[@text='Android UI Widgets']")).click();
androidDriver.findElement(By.xpath("//android.widget.TextView[@text='EditText']/following-sibling::android.widget.ImageView")).click();
Thread.sleep(2000);
androidDriver.findElement(By.className("android.widget.EditText")).sendKeys(textPass);
String typedText = androidDriver.findElement(By.id("com.tutorials.learn.androidexample:id/txtedt")).getText();
Assert.assertTrue(textPass.equalsIgnoreCase(typedText));
}

@AfterTest
public void tearDown(){
androidDriver.quit();
}
}

13. To execute this test case

  1. Click on Option beside hammer icon
  2. Click and Select Edit configuration option
  3. Click on + icon of Add new configuration
  4. Select TestNG
  5. Select Test Kind as Class
  6. Select class as HelloAppium
  7. Click on Apply and Ok

Right click on anywhere in the class and select Run option.

Booom!!!

It will start executing your test case. Monitor Device and Appium logs simultaneously , It will execute your test.

What if App is already installed on device. We can save execution time where appium copies apk from local and install it on device

But how can we do that? We would need adb commands for this.

  1. Launch application in device
  2. Make sure you are on the home screen of an application
  3. Open command prompt
  4. hit command adb shell
  5. Hit command dumpsys window windows | grep -E ‘mCurrentFocus’
  6. It will return app package name with app activity which is opened in the device
  7. Please check below screenshot for the open activity it gives below output in command prompt

To utilize package and acitivty we have to replace our appium:app capability with 2 new capabilities appPackage and appActivity

capabilities.setCapability("appPackage","com.tutorials.learn.androidexample");
capabilities.setCapability("appActivity","com.tutorials.learn.androidexample.MainActivity");

setCapability() will be

@BeforeTest
public void setCapabilities(){
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("appium:deviceName", "emulator-5554");
capabilities.setCapability("appium:automationName", "Appium");
capabilities.setCapability("appium:platformVersion",
capabilities.setCapability("appPackage","com.tutorials.learn.androidexample" );
capabilities.setCapability("appActivity","com.tutorials.learn.androidexample.MainActivity");
try {
androidDriver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"),capabilities);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}

Now run you automation script again and you will get same execution report.

Thanks for reading!!

--

--

Monil Joshi

I am having an 8+ years of experience in software testing. Working with Web, Mobile and API technologies. Visit my GIT https://github.com/monilj