Quote

"Between stimulus and response there is a space. In that space is our power to choose our response.
In our response lies our growth and freedom"


“The only way to discover the limits of the possible is to go beyond them into the impossible.”


Friday 7 September 2012

Automating Android Browser Testing Using Android WebDriver


If your web application supports android platform, then you need to perform functional verification of your application from the android platform. Just like for a desktop appication you can use the WebDrivers Android avatar to perform automated end-to-end tests that ensure your site works correctly when viewed from the Android browser. The advantage of using the Android WebDriver is that it supports all the core WebDriver APIs plus it also provides mobile specific features, such as finger scroll and long presses and also supports the HTML5 features, such as local storage, session storage, and application cache. Native events are used by the Android Webdriver to interact with the web page which is rendered using the WebView, which is the component used for rendering web pages by the android browser.

Now when we know the basics of the Android WebDriver let us start the installation process. The first question is, What are the pre-requisites for isntalling the Android WebDriver? The setup and exercises that we will be doing require the following:

1) Eclipse with ADT
2) Android SDK installed
3) Android WebDriver
4) Android device emulators or real android devices

Once you have the above requirements ready then the following steps need to be followed to setup end-to-end web application testing on Android:

Step 1: Getting the device or the emulator ready


If you have a physical Android device you can connect the device to your machine using a USB. But if you do not have a physical Android device you can use the Android emulators. The steps to setup the emulator are as follows:

-- Create an Android Virtual Device using the command line: You can use the 'AVD Manager.exe' in the Android SDK to launch a GUI which helps in creating an Android Virtual Device. However, we can perform the same task using the command line as well. Navigate to the directoty ~/android-sdk/tools and run the command:
android create avd -n YourAndroid -t 12 -c 100M 


Select no where you are asked to create a custom hardware profile as it is not required.

After creating the AVD named YourAndroid above, now you can start the emulator using the following command:
emulator -avd YourAndroid &
Once your emulator or the device is ready we are done with the environment setup.

Step 2: Running the tests Using Remote WebDriver Server


The android server is an android application(.apk) which contains an HTTP server. The WebDriver commands from the JUnit tests make a request to the Android Server which sends these requests to the Android WebDriver, which processes and sends an appropriate responce back.

You need to get the serial ID of the device or the emulator to be able to install the Android Server to it. You can run the following command to get the list of available devices:

adb devices

We need to navigate to the ~/android-sdk/platform-tools directory on the command line to execute the above command. The output of the command lists all the available devices, such as:
List of devices attached
emulator-5554   device


Here emulator-5554 is the serial number which needs to be passed to the install command for installing the Android Server. To install the Android Server, you need to first download it from the download link. After downloading the Android Server.apk you run the following command to install the Android Server to the target emulator/device:

adb -s <serialId> -e install -r  android-server.apk 

In our case the SerialID is emulator-5554 and the current server version available on the download page is android-server-2.21.0.apk. Hence we will be running the following command to install the android server to our virtual device having the serial ID emulator-5554:

adb -s emulator-5554 -e install -r android-server-2.21.0.apk

The output of the command would be as follows:

To be able to install applications that are coming from the Android Market/ Playstore you need to configure your device or the emulator. Make sure you have Setting-->Applications-->Unknown Sources checked to be able to install applications from outside the Android Market. Now that the application is installed on the device/emulator we need to start application now. The application can be started from the device GUI or from the command line. The command to start the server application on the device is as follows:
adb -s <serialId> shell am start -a android.intent.action.MAIN -
org.openqa.selenium.android.app/.MainActivity -e debug true

so in our case the command will be:
adb -s emulator-5554 shell am start -a android.intent.action.MAIN -n org.openqa.selenium.android.app/.MainActivity -e debug true

The WebDriver icon on the device GUI shown below can also be used to start the Android Server application:

 After starting the Android Server we need to setup port forwarding so that the requests are sent from the host machine to the emulator. Port forwarding enables the Android Server on the emulator to be available to the host machine over http connection using the URL http://localhost:8080/wd/hub

Run the following command for port forwarding:
adb -s emulator-5554 forward tcp:8080 tcp:8080
Now the emulator will be available at http://localhost:8080/wd/hub.

Step 3: Writing and Executing Tests

Now we can write JUnit tests from eclipse and run them on the Android device. A simple JUnit test is as follows:


import junit.framework.TestCase;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.android.AndroidDriver;

public class TestAndroidWebDriver extends TestCase {
     
      public void testAndroid() throws Exception {

          WebDriver driver = new AndroidDriver();
          driver.get("http://satyamsing.blogspot.com");
          String title = driver.getTitle();
          WebElement e = driver.findElement(By.partialLinkText("Android"));
          e.click();
          e = driver.findElement(By.partialLinkText("Topic 3"));
          e.click();
          assertTrue("Got title: " + title, title.contains("Satyam"));
          driver.quit();

     }

}

Add the above test in your project using the following steps:

1) Create a test project and add selenium and JUnit jars as an external libraries to it
2) Create a class named 'TestAndroidWebDriver' and copy the above code to it
3) Compile and run the JUnit test

You can now see your test running on the Android as follows:

49 comments:

  1. i am not able to open the page !! it's showing ACCESS BLOCKED
    what to do for solving that ? help me in solving this problem.

    ReplyDelete
    Replies
    1. @Vinod: which page are you unable to open? It seems that a firewall is blocking the page. Try bypassing the firewall. More details will help to resolve the problem.

      Delete
    2. i followed all the steps mentioned above and copy pasted the example code , after running as junit test its showing ACCESS BLOCKED
      FILE DOWNLOAD HAS BEEN BLOCKED

      Delete
    3. Vinod: The above steps work fine. Are you using an emulator or a real physical device? What version of android are you using? Are you able to install the server on the device/emulator? Please make sure that you have Setting-->Applications-->Unknown Sources checked in the emulator or the device. If the problem still persists you can send me the screen shot and the logs @ satyamsing@gmail.com

      Delete
  2. Hi Satyam,
    Im new to android, can you tell me how to get the locaters in writing the test script for android web app(to get id,css etc)

    ReplyDelete
    Replies
    1. Locating elements on a web page in Android is same as in any other operating system. Same WebDriver APIs are used to access Webelements in Android as in any other supported browser. As in the example above 'driver.findElement(By.partialLinkText("Android"))' has been used. Similarly
      'driver.findElement(By.id("SomeID"))'
      'driver.findElement(By.className("ClassName"))'
      'driver.findElement(By.tagName("TagName"))'
      'driver.findElement(By.cssselector("DIV.SPAN"))'
      'driver.findElement(By.xpath("Xpath"))'
      'driver.findElement(By.linktext("exactLinkText"))'
      'driver.findElement(By.name("name"))'

      Delete
  3. thank u satyam,

    ReplyDelete
  4. Hi Satyam,
    when i tried to run a sample script of android web apptesting using web driver, facing this issue

    Could not find class 'org.openqa.selenium.android.AndroidDriver', referenced from method Sample_02.testGoogle

    Please help me
    Regards,
    Swetha

    ReplyDelete
    Replies
    1. Hi Swetha,

      It seems the webdriver classes are not in the 'CLASSPATH'. Please make sure that the webdriver jar is in the 'CLASSPATH' and then retry. If the problem persists you can send me the details to satyamsing@gmail.com

      Delete
  5. I have sent u the detail to ur mail.
    Thankyou

    ReplyDelete
  6. Hi,
    How do you manage to get locator id for mobile version of any web page? Is it always same id as normal webpage? Do you any specific addin to identify id or any identifier for mobile application?

    ReplyDelete
    Replies
    1. Hi Mrinal,

      The locator ID of the mobile version of a web page may be the same or different. If the web page is designed to render differently on mobile web then the locators will need to be identified separately for them.

      We can use user agent switcher on firefox/chrome to emulate the PC browser as a mobile web browser. Then firebug can be used to get the locator id's as in the web pages for desktops.

      Delete
  7. Thanks Satyam. Will surely give a try. :)

    ReplyDelete
  8. Satyam, great blog very informative! when I try to run my test I get
    Could not find class 'org.openqa.selenium.android.AndroidDriver'

    can u help
    I do have my webdriver in my class path

    ReplyDelete
    Replies
    1. This is what my test case looks like
      public class Test1 extends TestCase {

      public void testAndroid() throws Exception {

      WebDriver driver = new AndroidDriver();
      driver.get("http://satyamsing.blogspot.com");
      String title = driver.getTitle();
      WebElement e = driver.findElement(By.partialLinkText("Android"));
      e.click();
      e = driver.findElement(By.partialLinkText("Topic 3"));
      e.click();
      assertTrue("Got title: " + title, title.contains("Satyam"));
      driver.quit();

      }

      }

      Delete
    2. Can you please mention the jar name which is in the classpath. I tried to reproduce the issue by not starting the server apk but gives a separate error. You may want to enter the complete path of the AndroidDriver.class and try again.

      Delete
    3. This comment has been removed by the author.

      Delete
  9. path="C:/Android/android-sdk/extras/google/webdriver/android_webdriver_library.jar"

    is this the AndroidDriver?

    ReplyDelete
  10. so let me explain my configuration.

    1. I created an Android project called "SimpleAppActivity"
    2. Then I created an Android Test Project and associated it with my Android project above.
    3. in my test project I created a class file

    4. I select My test project and run as Android Unit Test

    Error:
    Could not find class 'org.openqa.selenium.android.AndroidWebDriver', referenced from method simple.app.test.TestOne.testGoogleWorks

    ReplyDelete
    Replies
    1. You need to put the class files in the 'CLASSPATH' not in the path as mentioned above by you. Then you need to put the selenium-server-standalone.jar in the 'CLASSPATH'. The class files in the jar can be verified by using a zip extractor. Put the standalone jar in the referenced library, deploy the server apk on the emulator/device and follow all the steps mentioned above, you should be able get it working.

      Delete
  11. I send you an email with screen shots to satyamsing@gmail.com. I hope that's ok

    ReplyDelete
    Replies
    1. Thats fine Zique. I will take a look at the screens and get back to you. Hopefully, by EOD today.

      Delete
  12. I received your email... I tried what you suggested and I am still getting that error.

    Let me ask you, do I need to create an Android Project and an Android Test Project?

    ReplyDelete
    Replies
    1. No you do not need to create Android project and Android Test Project if you use remote server approach. This blog post is for the remote server approach hence there is no need for creating the Android Project and Android Test project.

      It is needed if Android test framework is to be used.

      Delete
  13. Good news I got it to work!!! all along it was a problem with jar files not being in the correct path etc... Thanks for all your help

    ReplyDelete
  14. I am getting the error like "Could not find class 'org.openqa.selenium.android.AndroidDriver'"

    I given the class path C:\Program Files (x86)\Android_S3\android-sdk\extras\google\webdriver

    ReplyDelete
    Replies
    1. Hope you were able to resolve it. If now try putting the jars in the directory to the project classpath (Build Path\Libraries\Add External Jars)

      Delete
  15. I am getting below error while running the test by using junit org.openqa.selenium.remote.UnreachableBrowserException: Could not start a new session. Possible causes are invalid address of the remote server or browser start-up failure.

    ReplyDelete
    Replies
    1. If the issue persists can you please send the test code to satyamsing@gmail.com, so that I can try to reproduce and resolve it. Seems to be a known issue with selenium: http://code.google.com/p/selenium/issues/detail?id=4150

      Delete
  16. Hello
    can you please tell that
    how can we run tests directly from device or emulator....if once we made them ....????

    ReplyDelete
    Replies
    1. Executing test on device/emulator is supported most tools/frameworks. We can fire test from robotic APIs/tools on device/emulator but normally there is no business need to run test from device/emulator.

      Can you explain the scenario where it is required.

      Delete
  17. hello sir,

    I am getting following error:

    [2013-04-30 01:11:17 - aaaa] Android Launch!
    [2013-04-30 01:11:17 - aaaa] adb is running normally.
    [2013-04-30 01:11:17 - aaaa] Could not find aaaa.apk!

    please tell me the solution..



    ReplyDelete
    Replies
    1. Need setup and environment details to debug.

      Delete
  18. Hello Satyam,

    I had successfully installed android emulator and have prepared script using webdriver, but getting the below error please help..

    Below is my code and error description

    Error:[2013-05-14 15:39:11 - Webdriver_Android] Performing android.test.InstrumentationTestRunner JUnit launch
    [2013-05-14 15:39:11 - Webdriver_Android] Automatic Target Mode: using existing emulator 'emulator-5554' running compatible AVD 'AVD_for_Nexus_One_by_Google'
    [2013-05-14 15:39:13 - Webdriver_Android] Application already deployed. No need to reinstall.
    [2013-05-14 15:39:13 - Webdriver_Android] Launching instrumentation android.test.InstrumentationTestRunner on emulator-5554
    [2013-05-14 15:39:13 - Webdriver_Android] Failed to launch test

    Script:
    package com.android_samples.test;

    import java.util.concurrent.TimeUnit;

    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.android.AndroidDriver;

    public class Sample_Test_Debug {
    public static WebDriver driver;

    @Before
    public static void SetUp() {
    driver = new AndroidDriver();
    driver.manage().timeouts().implicitlyWait(1000, TimeUnit.SECONDS);

    }
    @Test
    public static void testTestJunit() {
    driver.get("www.google.com");
    driver.manage().timeouts().implicitlyWait(1000, TimeUnit.SECONDS);
    driver.findElement(By.id("gbqfq")).clear();
    driver.findElement(By.id("gbqfq")).sendKeys("testing");
    driver.findElement(By.id("gbqfb")).click();
    driver.findElement(By.linkText("Software testing - Wikipedia, the free encyclopedia")).click();
    }
    @After
    public static void TearDown() {
    driver.quit();
    }

    }

    Regards,
    Keerthi.

    ReplyDelete
  19. port forwarding: is done but http://localhost:8080/wd/hub not getting up.
    Any expert could you help me please im using actual android device and commands i ran as per below,
    I have already installed android-server-2.21.0.apk in device before.
    http://localhost:8080/wd/hub.

    E:\selenium\Android SDK\adt-bundle-windows-x86_64-20130522\sdk\platform-tools>ad
    b devices
    List of devices attached
    S5830598ae9ec device


    E:\selenium\Android SDK\adt-bundle-windows-x86_64-20130522\sdk\platform-tools>ad
    b -s S5830598ae9ec -e install -r android-server-2.21.0.apk
    can't find 'android-server-2.21.0.apk' to install

    E:\selenium\Android SDK\adt-bundle-windows-x86_64-20130522\sdk\platform-tools>ad
    b -s S5830598ae9ec shell am start -a android.intent.action.MAIN -n org.openqa.se
    lenium.android.app/.MainActivity -e debug true
    Starting: Intent { act=android.intent.action.MAIN cmp=org.openqa.selenium.androi
    d.app/.MainActivity (has extras) }

    E:\selenium\Android SDK\adt-bundle-windows-x86_64-20130522\sdk\platform-tools>
    E:\selenium\Android SDK\adt-bundle-windows-x86_64-20130522\sdk\platform-tools>ad
    b -s S5830598ae9ec forward tcp:8080 tcp:8080

    E:\selenium\Android SDK\adt-bundle-windows-x86_64-20130522\sdk\platform-tools>ad
    b -s S5830598ae9ec forward tcp:8080 tcp:8080

    ReplyDelete
  20. Hi Satyam,

    Please explain create the project steps
    1.Can I create java project or android test project?
    please explain eclipse steps to create the project.

    Regards,
    Lakshman

    ReplyDelete
  21. Hi satyam ,

    I have successfully configured the Emulator and started the web driver. But i have some doubt in running the sample code using eclipse. can u plz tell the procedure to run the test in eclipse.

    Regards,
    Nelson

    ReplyDelete
    Replies
    1. Hi Nelson,

      Sorry for the late reply, had been of to some other high priority work. Let me know if the issue is not yet resolved. Please specify the step you have difficulty running in.

      Delete
    2. I ve resolved that issue... but having problem with getting the web element id inside the emulator with webdriver....can u plz tell how we get the id,className etc coz we cannot capture the inputs here in webdriver....

      Delete
  22. import org.openqa.selenium.android.AndroidDriver;
    Black colour line appears on "AndroidDriver" when i Paste the code in eclipse.Please help

    ReplyDelete
  23. Nice post. It helps me a lot. Thanks for posting.

    ReplyDelete
  24. Hi, This is the way I created project. But i am getting message as below.

    1. I created an Android project called "SimpleAppActivity"
    2. Then I created an Android Test Project and associated it with my Android project above.
    3. in my test project I created a class file

    4. I select My test project and run as Android Unit Test

    Error:
    Multiple markers at this line
    - The type org.openqa.selenium.HasTouchScreen cannot be resolved. It is indirectly referenced from required .class files
    - The type org.openqa.selenium.html5.BrowserConnection cannot be resolved. It is indirectly referenced from required .class files

    ReplyDelete
    Replies
    1. Hi, before running the test script selenium-2.31.0. jar file should be present in your buid path. Try this!

      Delete
  25. hi sathyam,

    i am facing the following error while adding the andriod driver and importing that.

    "org.openqa.selenium.hastouchscreen cannot be resolved,it has referenced from another class file"

    so pls suggest me solution

    thanks
    karthikeyan

    ReplyDelete
  26. This comment has been removed by the author.

    ReplyDelete
  27. Hi, before running the test script selenium-2.31.0. jar file should be present in your buid path. Try this!

    ReplyDelete
  28. Hi, please help me I need to run a script for android selenium driver but I encountered this error:
    The type org.openqa.selenium.HasTouchScreen cannot be resolved. It is indirectly referenced from required .class files
    - The type org.openqa.selenium.html5.BrowserConnection cannot be resolved. It is indirectly referenced from required .class files

    and my build path contains selenium 2.46 and selenium-android-driver 2.39

    ReplyDelete