Introduction to Appium

Appium is an open-source tool for mobile automation. It allows automation of native, mobile web and hybrid mobile applications. Using Appium, we can automate iOS, Android and Windows Phone apps on both emulator/simulator and on physical mobile devices.

However, the real beauty of Appium lies in its ‘cross-platform’ support. It lets us write tests for multiple platforms (iOS, Android, and Windows Phone), using the same API. That means you can write your test for Android platform and use that same test for iOS or Windows Phone! The underlying API remains same. This results in a large amount of code reuse between different test suites.

Another cool feature of Appium is its ability to automate without recompiling the app. That means we don’t need access to our application code. Other mobile automation tools such as Calabash and Frank requires an extra agent compiled with the app code. But there’s no such requirement for Appium! This essentially means you will be testing the same app which you are going to submit in app stores.

Appium’s Philosophy

  • You shouldn’t have to recompile your app or modify it in any way in order to automate itAs we saw earlier in this Appium tutorial, Appium does not require any extra agent in application code. Therefore, we don’t need to recompile or modify our app.
  • You shouldn’t be locked into a specific language or framework to write and run your tests Appium allows writing tests in Ruby, Python, Java, Node.js, Objective-C, PHP and C#. Users need not learn any new language/framework to use it.
  • Mobile automation framework shouldn’t reinvent the wheel when it comes to automation APIsAppium uses WebDriver API, which is pretty well known among automation testers already. So, it doesn’t reinvent the wheel by introducing the entirely new API.
  • Mobile automation framework should be open source, in spirit and practice as well as in name!This philosophy is obvious. Appium is freely available and users can freely modify it as per their requirements. Truly open source in spirit and in practice!

Appium’s Architecture

The most important aspect of Appium architecture is its client/server nature. Appium follows a client/server architecture. So at this point, it would be important for us to understand what is client and what is server in its design. We will check them out one by one below.

Server: If you have ever used Selenium RC before, you’ll find that Appium works in a similar line. Just like Selenium server in Selenium RC, Appium essentially is a server at its very core. It facilitates communication between client and a mobile device. It is important to note here that Appium server is written in Node.js. That’s why we need Node.js installed in our system to use it.

Client: Client in Appium terminology is one of the client libraries (in Java, Ruby, Python, PHP, JavaScript, and C#) available for Appium. These libraries provides mobile specific commands (such as multi-touch) in addition to standard Selenium commands.

Working of Client and Server

When Appium server starts, it basically exposes a REST API to client. Client initiates a session with it using a JSON ‘desired capabilities’ object. Server, in turn, starts a session and responds to client with a session ID. This result is the creation of a session between client and server.

Now that the session is established between them, client sends automation commands to server. Appium server executes those commands on mobile device and responds to client with results.

At this point, it is worth noting that Appium does not execute commands on mobile devices directly. Instead, it invokes vendor-provided automation frameworks specific to the platform that we are testing on. Vendors like Apple, Google and Microsoft provides automation frameworks for their platforms. Appium server hooks to these frameworks and carries out automation on device.

Appium tutorial: Appium Architecture

Creating Android Virtual Devices (AVD)

We don’t need a real device all the time to test your apps in various API versions and different resolutions. So, the Android SDK comes with a pretty neat tool called the emulator, which allows you to emulate the Android devices. The emulator is pretty straight forward to use. When you want to launch a device, all you need to do is open the Android Virtual Device (AVD) tool either from your SDK folder or straight
from Eclipse. Then, you can either set up a new device with its own memory card, CPU, and screen size as well as other custom features or you can select one of the pre-configured devices from a list.

Before creating an emulator, you need to install latest & required APIs versions from Android SDK manager. 

To emulate a device from Eclipse, try the following steps:
1. Click on the AVD manager icon on your Eclipse toolbar.
2. Then AVD will pop up. You can either select a preconfigured featured device or you can set up a device according to your own criteria. As of now, let’s stick to configuring our own devices.

avd-manager
3. Click on New button
4. Then Create new Android Virtual Device (AVD) dialog box should pop up. You need to fill in some metrics for the new virtual devices and give it a name. You can enter whatever you feel here as this post is just to get you to emulate your first device.

AVD_NEWButton
5. Once you’re done, click on OK. The new device should show up in the AVD dialog box.
6. Click on the device you just created and click on Start….
At this point, the AVD will prompt you for the screen-size options; the default values aren’t too bad. Click on Launch when you’re done, and in a few seconds your new AVD will start up.

AVD_6
Creating your Own Android Virtual Devices from CLI (Terminal)

1. You can find a list of the system images available to you by using the following
command: path of Android SDK/tools$ ./android list targets
ex: cd /home/Android-sdk/tools; ./android list targets

This will list out few targets with IDs. This depends on the images you’ve downloaded from SDK manager

2. Create the AVD using the following command:

path of Android SDK/tools/android create avd –n [name of your new AVD] –t [system image target id]
You need to decide on a name for the AVD you’ve just created, which you will
specify using the –n switch. The system image ID you selected from the previous step
must be specified using the –t switch. If everything goes well, you should have just
created a brand new virtual machine.

3. You can launch your brand new AVD using the following command:
path of Android SDK/tools/emulator –avd [avd name]
Here, [avd name] is the AVD name you decided on in the previous step. Yea that’s it, your new AVD should start in a moment.

 

2018-04-06 16_48_39-Greenshot

Okay you wanna configure your emulator with external storage/Memory card, then try navigate to pathofSDK and type the command:

android create –avd –n [avd name] –t [image id] –c [size][K|M]
your virtual device emulates some external storage using the –c switch when you create it.
ex: android create –avd –n myFirstAVD –t 7 –c 4028M

Here -n = myFirstAVD, which is my AVD name, -t=7, which is target ID having single ABI and –c =4028M, allocated memory 4GB.

Partitioning sizes in emulator
Another very useful thing that you may want to do is to  specify how much space you’d like to allocate the internal storage partitions. You can do this by using the -partition-size switch, which you specify when you invoke the emulator as shown in the following command:
emulator –avd [name] –partition-size [size in MBs]

You will also need to supply a size for the partitions. By default, the unit of measurement is megabytes (MBs).

That’s it, now you know how to create a virtual device using GUI and CLI. Not only AVD Manager, we also have Genymotion for virtual devices. As of now I’m not talking about Genymotion. We will see that later.

ADB Commands

To install an app in your device we can use the following command:

adb install [option] <path>
ex: adb install test.apk
This command will let you install an app in your emulator or real device connected to your system. There are few other switches which can be used with adb install

switch -r
adb install -r test.apk
This will replace the existing application installed in your device

switch -s
adb install -s test.apk
This will install application on the sdcard present in the device.

To uninstall an app from the device using adb command:

adb uninstall [options] <PACKAGE>
ex: adb uninstall com.test.app

Just like switches for install, there is a switch for uninstall command too

adb uninstall -k com.test.app
This keeps the data and cache directories around after package removal.

Copying files from/to an AVD

1. To copy files from your device to your system. Then use the below command:
adb pull [path to copy from] [local path to copy to]
ex: adb pull /sdcard/pictures/charan.png /home/Desktop/

2. To copy files onto an AVD, you can use the following command:
adb push [local path to copy from] [path to copy to on avd]
ex: adb push test.apk /sdcard
This will copy test.apk to sdcard present in the device. This is one of the ways to install

3. To know what all packages present in your device then try below command:
adb shell pm list packages

This will print all the packages (both enabled and disabled)

There are few switches which can be used to obtain desired output
adb shell pm list packages -e
This will show only enabled packages.

adb shell pm list packages -s
This will print all the system packages.

adb shell pm list packages -3
This will show third party packages.

adb shell pm path com.android.phone
This will show the path of the mentioned package

adb shell pm clear com.test.abc
This will delete all data associated with a package.

Desired Capabilities

Desired Capabilities got introduced in Selenium to work with lot of browser capabilities like handling browser cookies , SSL security popup blah blah.
But why are we using this in Appium?
Using Desired Capabilities we can communicate with Appium server by sending a POST request, saying that I’d like to start a session with so and so platform and platformversion, browser etc…Now the server understands it and starts a session with the capabilities which we have set. Still confused?
Desired capabilities is a JSON object (keys and values pair). So, there are few capabilities in-built. We need to set the capability name as ‘key’ and capability value as ‘value’. The capabilities keys are case sensitive. You need to follow correct syntax to set key and value. Without setting these capabilities, you can’t even establish a session.

Let’s see few capabilities which needs to be used to start a session

androidDeviceReadyTimeout: To set the timeout in seconds for a device to become ready after booting. You need to set ‘androidDeviceReadyTimeout’ as key and desired seconds as ‘value’

DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability(“androidDeviceReadyTimeout”,”20″);

app:  Appium will install the app binary on the appropriate device. You don’t need this capability, if you’re using appPackage & appActivity. You need to pass ‘app’ as key and your local path(/home/test.apk) as value to set the capability”

caps.setCapability(“app”,”/Localpath/Your.apk”);

appActivity: This is to set the Android activity that you want to launch from your package. You need to set ‘appActivity’ as key and ‘com.android.contacts’ as value.

caps.setCapability(“appActivity”, “com.android.calculator2.Calculator”);

appPackage: This capability is for the Java package of the Android app that you want to run. You need to set ‘appPackage’ as key and your package name as value.

caps.setCapability(“appPackage”, “com.android.calculator2”);

appWaitActivity: This is to wait for the activity you’d like to use

caps.setCapability(“appWaitActivity”,”com.android.calculator2.Calculator”);

appWaitPackage: Similar to appWaitActivity, this capability will wait until if finds the desired package

caps.setCapability(“appWaitPackage”,”com.example.android.myApp”);

autoLaunch: This capability is used to install and launch the app automatically. The default value is set to true. We need to set ‘autoLaunch’ as key and value as ‘false’

caps.setCapability(“autoLaunch”,”false”);

automationName: This capability is used to define the automation engine. Here we need to set ‘automationName’ as key and your desired engine (Appium, Selendroid) as value

caps.setCapability(“automationName”,”Selendroid”);

autoWebview: If you are automating hybrid apps and want to move directly into the Webview context, then you can set it by using this capability; the default value is false. You need to set ‘autoWebview’ as key and ‘true’ as value”

caps.setCapability(“autoWebview”, “true”);

avd:  This is to set the name of avd that you want to launch. You need to set ‘avd’ as key and ‘Myavd’ as value.

caps.setCapability(“avd”,”Myavd”);

avdLaunchTimeout: This capability will help you define how long you need to wait. Value should be in milliseconds

caps.setCapability(“avdLaunchTimeout”,”150000″);

browserName:  You need to invoke a browser to automate Mobile web apps. For that you need to set ‘browserName’ as key and your desired browser (chrome, safari..) as value.

caps.setCapability(“browserName”, “Chrome”);

chromedriverExecutable:  You can give the absolute local path to the WebDriver executable.

caps.setCapability(“chromedriverExecutable”,”pathto/webdriver”);

deviceName:  You need to set device name, so that the user agent would be your device name. To know your device name, type ‘adb devices’ in Terminal. Now set the key as ‘deviceName’ as ‘Samsung s5’ as value. If you’re using emulator just set emulator name as value.

caps.setCapability(“deviceName”, “Samsung s5”);

deviceReadyTimeout: You can set the timeout while waiting for the device to be ready.

caps.setCapability(“deviceReadyTimeout”,”15″);

language:  This is used to set the language on the simulator. You need to set ‘language’ as key and ‘en’ as value

caps.setCapability(“language”,”fr”);

locale:  This is used to set the locale for the emulator, for example, fr_CA. This is used in case of I18N, L10N. This is not so helpful unless you knew lil French.

caps.setCapability(“locale”,”fr_CA”);

newCommandTimeout:  We can define timeout for how long  appium server should wait for a new command. You need to set ‘newCommandTimeout’ as key and ’30’ as value. This means, it will wait till 30 seconds.

caps.setCapability(“newCommandTimeout”, “30”);

Orientation: This is used to set orientation for emulator. Maybe LANDSCAPE or PORTRAIT

caps.setCapability(“orientation”, “PORTRAIT”);

platformName: It is used to set the mobile OS platform in which we’re about to start our session. You need to set ‘platformName’ as key and ‘Android’ as a value.

caps.setCapability(“platformName”,”Android”);

platformVersion: It is used to set the mobile OS version. Each Android API has a version. So you need to set ‘platformVersion’ as key and ‘4.4.2’ as value.

caps.setCapability(“platformVersion”,”4.4.2″);

useKeystore: This is to set keystores. You need to set ‘useKeyStore’ as key and ‘false’ as value.

caps.setCapability(“useKeystore”,”false”);

Locating/Identifying UI Elements

In Selenium there are few locators to identify elements in mobile apps. Generally, to find the elements we use UIautomator for native and hybrid apps. This article helps you to know about UIautomator and other various locators. As you know how to create a new AVD from my previous article, we will use an Emulator and Calculator app to identify elements in the calculator app. Within no time you’ll learn how to use UIautomator and locating the mobile app elements. Just hold tight and follow the below steps:

What Is UIAutomator Viewer?
UiAutomator is a tool that comes with Android SDK (>= API 16) which is helpful to automate the UI. It’s a good GUI tool to scan and analyze the UI components of an Android application. For ease, it captures screenshot of our device where we can identify the elements. This works for only Android. As I’m focusing only on Automating Android Apps here. This UIAutomator would be a .bat file in windows OS and it would be a script file in Unix systems. This comes with Android SDK itself. This tool works only when you’re connected to a device (Maybe real/ emulator). UIAutomator Viewer does not support WebView.

Launch UIAutomatorviewer
For Windows operating system:
To launch UIAutomatorviewer, go to the path where you’ve installed SDK and find uiautomatorviewer.bat. Double click on it to launch.
For Unix based operating system:
Go to the path where you’ve installed SDK and find uiautomatorviewer script to open it. Make sure that you’re connected with a device

Once it’s launched, then click on calculator app in your device. Now in UIAutomatorViewer tool, Click on Device Screenshot image button present in the toolbar. Now this will capture a screenshot of the app which was launched.

2018-04-06-16_53_50-greenshot.png

On the Right top. it displays calculator app’s UI element’s hierarchy view. And the bottom part will display the properties in detail of selected element. This is how you can inspect any element of android native app using UIAutomatorViewer tool. You just need to click on element and it displays element’s properties in detail. It’s good to save the screenshots captured by that tool for our use at later point of time.

You may wonder, this UIAutomator works only for native and hybrid apps but what about mobile web apps. Yeah, this will not work for web apps. We can follow Selenium approach to inspect elements in web apps. Just like in Selenium, we need to invoke a browser and open dev-tools to inspect elements. But we need to add a plugin called ‘Chrome ADB plugin’ to your desktop chrome browser. Recently I came across two chrome extensions. Chrome ADBADB – Chrome. You can try either of them.

Once you set up your device for debugging, then the chrome://inspect/#devices page
will be displayed with all the connected devices along with the open tabs and web views. Make sure Discover USB devices is checked. There will be link ‘inspect‘. Click on that link to open developer tools. Now its just same as in Selenium, Identify the element by mouse hovering the element.

Now, let’s see different locators supported by the Appium driver.

  • Finding elements by ID
  • Finding elements by name
  • Finding elements by className
  • Finding elements by AccessibilityId
  • Finding elements by AndroidUIAutomator
  • Finding elements by Xpath

 

Locating/Identifying App Activity & App Package Name

Finding Package Name, Activity Name, Device Name
As you know, to start a session we need to set Desired Capabilities. Among those, we need to set Package name and Activity name capabilities as well. There are several methods to find package and activity name and below I’ve listed the simple method.
By using commands in Terminal :  Make sure the app is installed on the device and the app is on the focus.
C:\Users\vidhyasagarp>adb devices
List of devices attached
emulator-5554 device

C:\Users\vidhyasagarp>adb shell
generic_x86:/ $ dumpsys window windows | grep mFocus
mFocusedApp=AppWindowToken{7f5f07e token=Token{dcbca00 ActivityRecord{a4c5883 u0 com.android.calculator2/.Calculator t14}}}

Package Name : com.android.calculator2

Activity Name : .Calculator

 

Example script

package AppiumDemo.AppiumDemo;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.Test;

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.MobileCapabilityType;

public class Calculator {

public static void Sum(String[] args) throws Exception {
Sum();
}

@Test()
public static void Sum() throws InterruptedException, IOException {

// To start Appium Server
AppiumDemo.AppiumDemo.AppiumServerJava.startServer();

File appDir = new File(System.getProperty("user.dir"));
File app = new File( appDir, "Calculator.apk");

// Created object of DesiredCapabilities class.
DesiredCapabilities capabilities = new DesiredCapabilities();

capabilities.setCapability("app", app.getAbsolutePath());

capabilities.setCapability("deviceName", "emulator-5554");

capabilities.setCapability(CapabilityType.BROWSER_NAME, "Android");

// Set android platformName desired capability. It's Android in our case here.
capabilities.setCapability(MobileCapabilityType.PLATFORM, "Android");

capabilities.setCapability(MobileCapabilityType.VERSION, "7.1.1");

// Set your application's appPackage if you are using any other app.
capabilities.setCapability(MobileCapabilityType.APP_PACKAGE, "com.android2.calculator3");

capabilities.setCapability(MobileCapabilityType.APP_ACTIVITY, "com.xlythe.calculator.material.Theme.Orange");
capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());

capabilities.setCapability("noReset", "true");

URL url = new URL("http://127.0.0.1:4725/wd/hub");

AppiumDriver<MobileElement> driver = new AndroidDriver<MobileElement>(new URL("http://127.0.0.1:4725/wd/hub"), capabilities);

driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

String capabilites = ((AppiumDriver<MobileElement>) driver).getCapabilities().toString();
ArrayList<String> capabilitesList = new ArrayList<String>(Arrays.asList(capabilites.split(",")));
for (int i = 0; i < capabilitesList.size(); i++) {
System.out.println(+i + ":" + capabilitesList.get(i));
}

// Click on DELETE/CLR button to clear result text box before running test.
driver.findElement(By.id("com.android2.calculator3:id/del")).click();

// Click on number 2 button.
driver.findElement(By.id("com.android2.calculator3:id/digit_2")).click();

// Click on + button.
driver.findElement(By.id("com.android2.calculator3:id/op_add")).click();

// Click on number 9 button.
driver.findElement(By.id("com.android2.calculator3:id/digit_9")).click();

Components.Waits.forElementToBeClickable(driver, pageObjects.calculator.button_Equal);

// Click on = button.
driver.findElement(By.id("com.android2.calculator3:id/eq")).click();
// Get result from result text box.
String result = driver.findElement(By.id("com.android2.calculator3:id/formula")).getText();

//System.out.println("Number sum result is : "+result);

if(result.equals("11"))
{
Assert.assertTrue(true, "Result is not matching");
}
else
{
Assert.fail("Result is not matching");
}
}

@AfterTest
public void End() {
// To stop the Appium Server
AppiumDemo.AppiumDemo.AppiumServerJava.stopServer();
}
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s