Tuesday, 16 February 2016

A Glance on Appium


                                        


Appium an open source testing framework that is based on selenium web driver that is extended with new classes to support mobile applications and hybrid testing    


 Appium extends  Remote Webdriver to support mobile application automation, providing:
  • Identification of the application to automate
  • Launching application either directly from capabilities or with launchApp() method
  • Functionality to support mobile applications such as swipe,tap,Zoom,Rotate
  • Support for OS automation selectors:
                              UIAutomation for iOS
                              UIAutomator for Android API level 16 or higher
Google's Instrumentation for Android API level 15 or less(Selendroid)
It uses JSON wire protocol internally to interact with iOS and Selenium Webdriver for android native applications.Appium uses client-server architecture,this means a client written in any language can be used to send the http requests to the server.So you can manage your test environment as you like.Appium supports the below  mentioned client libraries:Java, Ruby, Python, PHP, JavaScript, and C#.

Identifying Objects: Identifying objects on different type of mobile applications can be done in different ways.
Web applications :DOM objects
Native applications : Appium automation framework
Hybrid application :Appium automation framework
         In the world of mobile application identifying objects is not that simple.Apple has its own set of proprietary set of UI elements and android has its own.
Appium references the UI elements using the name provided by the proprietary description file and this is appium framework objectory.
Appium framework uses two different objectory representation this means we need to create two different tests one for iOS and another for Android.Each object is defined by set of attributes that defines what is actually displayed.For ex:Text attribute defines text that is displayed.
 
Appium Drivers:Appium supports Android and iOS differently.The way Appium work is the different automation drivers for the platforms,which means we need to write different tests for platform.
Currently appium supports two flavors of automation driver.
AndroidDriver class-supports android applications.
iOSDriver class-for applications in iOS environment







Wednesday, 27 January 2016

How to Start Appium Server Programmatically?

      Now let’s look on how to start Appium Server Programmatically.


So here we use two Appium classes

1.AppiumDriverLocalService

2.AppiumServiceBuilder

Exceptions can be :

1.AppiumServerHasNotBeenStartedLocallyException
2.InvalidNodeJSInstance
3.InvalidServerInstanceException

1.AppiumDriverLocalService: Here I am going to list only few simple methods which can be used with this class.

Modifier and Type
Method and description
static AppiumDriverLocalService
buildDefaultService()
static AppiumDriverLocalService
buildService(AppiumServiceBuilder builder)
boolean
isRunning()
void
start() Starts the defined appium server
void
stop() Stops this service is it is currently running.
URL
getUrl()

2.AppiumServiceBuilder: Similarly here some of the methods that can be used .

Modifier and Type
Method and description
AppiumServiceBuilder
usingAnyFreePort()Configures the appium server to start on any available port.
AppiumServiceBuilder
usingDriverExecutable(File nodeJSExecutable)
Sets which Node.js the builder will use.
AppiumServiceBuilder
usingPort(int port)
Sets which port the appium server should be started on.A value of 0 indicates that any free port may be used.
AppiumServiceBuilder
withAppiumJS(File appiumJS)
AppiumServiceBuilder
withLogFile(File logFile)
Configures the appium server to write log to the given file.

Since we need to start Appium server before testcase run lets use @BeforeClass annotation.
Try this::
@BeforeClass
AppiumDriverLocalService service = AppiumDriverLocalService.buildService(new AppiumServiceBuilder().usingAnyFreePort().usingDriverExecutable(new File("path to node")).withAppiumJS(new File("path to appium.js")));

To start the server:
service.start()

To stop the server which can be called after all execution of testcases:
service.stop()

For Ubuntu Users::
How to find path to node?
Open Terminal and type which node .If node.js is installed it will show output similar
/home/deepa/.linuxbrew/bin/node

Note :@BeforeClass and @AfterClass should be defined as static.
AppiumDriverLocalService should be static.
stop() and start() should be defined as void.

To start the server programmatically you have to remove this line in your previous program
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), cap);
and replace with
driver = new AndroidDriver(new URL(service_url),cap);
Where service_url =service.getUrl().toString();

For test with below code use this apk:APK to be downloaded for this example

Complete code:(Changed code marked in blue w.r.t First Test Case in my blog:Your First TestCase)

package com.test.helloworld;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.MobileCapabilityType;
import io.appium.java_client.remote.MobilePlatform;
import io.appium.java_client.service.local.AppiumDriverLocalService;
import io.appium.java_client.service.local.AppiumServiceBuilder;

public class AppiumTest {
   AndroidDriver driver;
   static AppiumDriverLocalService service;
   static String service_url;

   @BeforeClass
   public static void appiumServer() throws Exception {
       service = AppiumDriverLocalService.buildService(new AppiumServiceBuilder().usingPort(0).usingDriverExecutable(new File("path to node")).withAppiumJS(new File("path to appium.js")));
       service_url = service.getUrl().toString();
       service.start();
   }

   @Before
   public void testCaseSetUp() throws MalformedURLException {
       File appDir = new File("src");
       File app = new File(appDir, "app-debug.apk");
       DesiredCapabilities cap = new DesiredCapabilities();
       cap.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID);
       cap.setCapability(MobileCapabilityType.DEVICE_NAME, "Android device");
       cap.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, "100");
       cap.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
       driver = new AndroidDriver(new URL(service_url),cap);
       //fresh installs the app everytime if fullReset to True
       cap.setCapability("fullReset", true);
   }

   @Test
   public void testHelloWorld() throws Exception {
       //find text HelloWorld and assert
       WebElement text1 = driver.findElement(By.xpath("//android.widget.TextView[@index='0']"));
       Assert.assertEquals("HelloWorld", text1.getText());
       //Click Menu and asset settings
       driver.findElementByName("More options").click();
       Assert.assertEquals("Settings", driver.findElementById("title").getText());
   }

   @After
   public void testCaseTearDown() {
       if (driver != null)
           driver.quit();
   }

   @AfterClass
   public  static  void stopServer(){
       service.stop();
   }
}

Now run the test (since I have used Android Studio here is the screenshot of the same)

Monday, 25 January 2016

Your First TestCase

After set-up now you can write your first Test case:
  
1.First create the folder->click main in app folder->Right click on the package ->Click on 'create Java Class.

2.Set Desired Capabilities:
Desired capabilities are options that can be used to customize and configure the browser session.
This tells Appium server what kind of automation we're interested in.

automationName   :which automation engine to use: Appium(default) or Selendroid
platformName     : which mobile OS              : iOS ,Android,FirefoxOS
platformVersion  : Mobile OS version            : 5.1,7.1,4.0
deviceName           :  Kind of mobile device or emulator: Galaxy S4,iPad Simulator
app                         :The absolute local path or remote URL to .ipa or .apk file:/abs/path/to/my.apkor   http://myapp.com/app.ipa(Note that this capability is not required for Android if you specify appPackage and   appActivity capabilities )
browserName       : Name of mobile web browser to automate. Should be an empty string if automating an app instead.‘Safari’ for iOS and ‘Chrome’, ‘Chromium’, or ‘Browser’ for Android
newCommandTimeout :How long (in seconds) Appium will wait for a new command from the client before assuming the client quit and ending the session:
autoLaunch        :Whether to have Appium install and launch the app automatically. Default true

There is no need to mention all the desired capabilities
Now you need to mention only:platform name
                                                  device name
                                                   app
DesiredCapabilities cap=new DesiredCapabilities();
cap.setCapability(MobileCapabilityType.PLATFORM_NAME,MobilePlatform.ANDROID);
cap.setCapability(MobileCapabilityType.DEVICE_NAME, "Android device");
cap.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, "100");
cap.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());

3.Apk file
For your first program lets copy the apk file and paste in the source folder of your project.
For this example use this apk Apk file to Download

4.Next need to set the path of the apk file.
File appDir = new File("src");
File app = new File(appDir, "app-debug.apk");

5.Pass this absolute path to desired capabilities
cap.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());

6.Invoke driver:
For Android : AndroidDriver
For iOS        :iOS Driver
You need to create an object for Android driver class and pass two parameter.

1.Appium server listens to localhost in port 4723(http://127.0.0.1:4723/wd/hub)
2.Pass desired capabilities to server (so pass ‘cap’ as second argument)
AndroidDriver driver;
driver=new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"),cap );

7.Test Case here is:
Here we will install the app and check if there is a text HelloWorld and click on menu which shows settings.

Now open uiautomatorviewer (navigate to tools folder and type uiautomatorviewer)and find the elements unique identifier.

In Appium you have to do trial and error to locate the elements.

a)Here HelloWorld can be found using Xpath .
Screenshot from 2016-01-25 19:34:50.png
//To find the HelloWorld
WebElement text1 = driver.findElement(By.xpath("//android.widget.TextView[@index='0']"));
//Assert the text displayed is same
Assert.assertEquals("HelloWorld", text1.getText());

b)Click on  Menu Object identifier(here Menu is found using content-description).Screenshot from 2016-01-25 19:35:28.png
driver.findElementByName("More options").click();

c)Settings (On Menu click Settings should be displayed).This is checked using Assert statements.
Screenshot from 2016-01-25 19:36:00.png
Assert.assertEquals("Settings",driver.findElementById("title").getText());

8)Use JUnit or TestNG framework.
Here we are using JUnit Test framework
JUnit test framework which uses annotations to identify methods that specify a test.
Some of the most used annotations:
@Test                       : The @Test annotation identifies a method as a test method.
@Test(timeout=100) : Fails if the method takes longer than 100 milliseconds.
@Before                    : This method is executed before each test.
@After                       : This method is executed after each test.
@BeforeClass           : This method is executed once, before the start of all tests.Method
                                    annotated with this should be defined as static.
@AfterClass              : This method is executed once, after all tests have been finished.Method
                                    annotated with this should be defined as static.
@Ignore                    : Ignores the test method.                                          

9)Here is the snippet of the code

Before executing the testcase(pass the capabilities to the appium server hosted on local server on port 4723).You can change the port to any free port.

@Before
public void testCaseSetUp() throws MalformedURLException {
  File appDir = new File("src");
  File app = new File(appDir, "app-debug.apk");
  DesiredCapabilities cap = new DesiredCapabilities();
  cap.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID);
  cap.setCapability(MobileCapabilityType.DEVICE_NAME, "Android device");
  cap.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, "100");
  cap.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
  driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), cap);
  cap.setCapability("fullReset", true);
}

After testcase is executed(quit the driver)
@After
public void testCaseTearDown()
{
  if (driver != null)
      driver.quit();
}

Testcase:1.Check Hello world is displayed
  2.Click on Menu
  3.Check ‘Settings’ is displayed
@Test
public void testHelloWorld() throws Exception {
  //find text HelloWorld and assert
  WebElement text1 = driver.findElement(By.xpath("//android.widget.TextView[@index='0']"));
  Assert.assertEquals("HelloWorld", text1.getText());

  //Click Menu and asset settings
  driver.findElementByName("More options").click();
  Assert.assertEquals("Settings", driver.findElementById("title").getText());
}

10.Complete code
package com.test.helloworld;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.MobileCapabilityType;
import io.appium.java_client.remote.MobilePlatform;
public class AppiumTest {
  AndroidDriver driver;
  @Before
  public void testCaseSetUp() throws MalformedURLException {
      File appDir = new File("src");
      File app = new File(appDir, "app-debug.apk");
      DesiredCapabilities cap = new DesiredCapabilities();
      cap.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID);
      cap.setCapability(MobileCapabilityType.DEVICE_NAME, "Android device");
      cap.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, "100");
      cap.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
      driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), cap);
      cap.setCapability("fullReset", true);
  }
  @Test
  public void testHelloWorld() throws Exception {
      //find text HelloWorld and assert
      WebElement text1 = driver.findElement(By.xpath("//android.widget.TextView[@index='0']"));
      Assert.assertEquals("HelloWorld", text1.getText());
      //Click Menu and asset settings
      driver.findElementByName("More options").click();
      Assert.assertEquals("Settings", driver.findElementById("title").getText());
  }
  @After
  public void testCaseTearDown()
  {
      if (driver != null)
          driver.quit();
  }
}

11.How to run the TestCase:
a)Set the build variant to unit test
b)Type appium on terminal and start the server
c)Right click on TestClass and Click on Run

Build variant Set-up


Appium server start
Screenshot from 2016-01-25 23:24:50.png

Appium logs after test executed
                                                                                                                                                            
Screenshot from 2016-01-25 23:25:42.png
Android Studio Terminal after testcases executed
Screenshot from 2016-01-25 23:26:10.png
Done!!!!!!!