Thursday, 24 July 2014

Automate (test) Android Application with Appium

Hello folks,

As discussed earlier, in this blog I will talk about platform setting up of your Android applications. I had mentioned in previous blog that, Appium uses JSON Wire protocol which in turn is a client-server architecture. So we need to set up both the parts separately.



Test Client

In the 2 tier architecture, your testcases/testscripts will act as the client. Appium provides you rich collection of client libraries in multiple programming languages such as Java/JavaScript/Ruby/PHP/Python/C#. This blog will explain the client set up using Java client libraries.


Create a Maven project in eclipse

To begin with create a maven project in your favorite IDE. Add following snippet to dependencies section in addition to JUnit.

<dependency>
 <groupId>org.seleniumhq.selenium</groupId>
 <artifactId>selenium-java</artifactId>
 <version>LATEST</version>
 <scope>test</scope>
</dependency>
<dependency>
    <groupId>io.appium</groupId>
    <artifactId>java-client</artifactId>
    <version>1.2.1</version>
</dependency>
<dependency>
 <groupId>com.googlecode.json-simple</groupId>
 <artifactId>json-simple</artifactId>
 <version>1.1</version>
 <scope>test</scope>
</dependency>
<dependency>
 <groupId>commons-lang</groupId>
 <artifactId>commons-lang</artifactId>
 <version>2.6</version>
 <scope>test</scope>
</dependency>
<dependency>
 <groupId>com.saucelabs</groupId>
 <artifactId>sauce_junit</artifactId>
 <version>1.0.18</version>
 <scope>test</scope>
</dependency>
<dependency>
 <groupId>com.google.code.gson</groupId>
 <artifactId>gson</artifactId>
 <version>2.2.4</version>
</dependency>

Also add following snippet to repositories.

<repository>
 <id>saucelabs-repository</id>
 <url>https://repository-saucelabs.forge.cloudbees.com/release</url>
 <releases>
  <enabled>true</enabled>
 </releases>
 <snapshots>
  <enabled>true</enabled>
 </snapshots>
</repository>

Now create a JUnit test case as follows.


package org.winster.appium;

import io.appium.java_client.AppiumDriver;

import java.io.File;
import java.net.URL;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;

public class AndroidWebViewTest {
  private AppiumDriver driver;

  @Before
  public void setUp() throws Exception {
    final File app = new File("D:/workspace/Android/HybridSample.apk");
    final DesiredCapabilities capabilities = new DesiredCapabilities();
    capabilities.setCapability(CapabilityType.BROWSER_NAME, "");
    capabilities.setCapability("deviceName", "Android Emulator");
    capabilities.setCapability("automationName", "Selendroid");
    capabilities.setCapability("platformName", "Android");
    capabilities.setCapability("app", app.getAbsolutePath());
    capabilities.setCapability("appPackage", "com.mcc.hybrid"); // Optional
    capabilities.setCapability("appActivity", ".HybridSample"); // Optional
    driver = new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
  }

  @After
  public void tearDown() throws Exception {
    driver.quit();
  }

  @Test
  public void webView() throws InterruptedException {
    final Set<String> contextNames = driver.getContextHandles();
    for (final String contextName : contextNames) {
      if (contextName.contains("WEBVIEW")) {
        driver.context(contextName);
      }
    }
    Thread.sleep(15000);
    final WebElement bookFlightButton = driver.findElement(By.id("register"));
    bookFlightButton.click();
    Thread.sleep(5000);
  }

}

This testcase is targetting an Android emulator. If you want to run it in a device, change device name to your device name.
This testcase also points to the Appium server installed in the localhost. If its a different server, use appropriate ip address.
The sample hybrid application that I have used in this example is a Cordova based application. The landing page has got a button with id 'register'. The testcase is trying to automate the click of that button.

Appium is at it's best when native app testing comes into place. But since we have a hybrid app here, I am switching to WEBVIEW context at the beginning of the test.

Appium Server

As pointed out earlier, the test client will make RESTful API requests to server for each operation whether it is switching the context or finding an element. The server will do the needful on the target (browser/emulator/device).
In order to set up the server, you have to set up your dev environment first as follows.

  • Download Android SDK and update your system PATH variables
  • Create an emulator with the targeted platform version
  • Install node in your machine
  • Install Appium server as follows. Get more info here.

npm install -g appium
Now start server with appium command. After starting the server, if you get logs as follows, you are good to go. Just run your test case.


D:\>appium &
info: Welcome to Appium v1.2.0 (REV e53f49c706a25242e66d36685c268b599cc18da5)
info: Appium REST http interface listener started on 0.0.0.0:4723
info: LogLevel: debug

Troubleshooting

If you get an error as follows while testing the app on emulator, you may have to start your emulator manually. It can be a defect on Appium as it tries to start it automatically.


debug: executing: "D:\Softwares\adt-bundle-windows-x86_64-20140702\sdk\platform-tools\adb.exe" kill-server
debug: Getting connected devices...
debug: executing: "D:\Softwares\adt-bundle-windows-x86_64-20140702\sdk\platform-tools\adb.exe" devices
debug: 0 device(s) connected
debug: Sent shutdown command, waiting for UiAutomator to stop...
warn: UiAutomator did not shut down fast enough, calling it gone
debug: Cleaning up android objects
debug: Cleaning up appium session
error: Failed to start an Appium session, err was: Error: Could not find a connected Android device.
debug: Error: Could not find a connected Android device.

If you are not able to deploy the application in device, just disconnect all the emulators and try again.
Please note that even if there is a mismatch in the device capability, Appium is intelligent enough to pick up the most appropriate one.


Cheers!

No comments:

Post a Comment