Configuring Appium Node Server with Selenium Grid

Introduction

Mobile devices are widely used in the world today. Therefore mobile application require vigorous testing. As android is the common mobile operating system we should be able to test it on multiple mobile operating systems.There can be multiple platforms (Android, iOS) and multiple devices which a Mobile App can support. However it involves a lot of resources and time for development to cover all of the tests across these devices. Now we can configure our Appium Node Servers with Selenium Grid.

How to configure and run test on Nodes?

Follow the following steps to configure the Android on Appium Node to Selenium Grid.

Step 1

Install the hub in the machine you have your code in the following manner.

java -jar selenium-server-standalone-2.47.1.jar -role hub

Step 2

Host 2 Appium Server Instances for 2 Mobile Devices. To configure 2 Running AVDs with Selenium Grid we need to create interfaces of the Appium Server. We have to run 2 instances of the Appium Server each associated with one of the Mobile devices and on another end connected to Selenium Grid.

 

Setting up an Appium Node instance for one device (Tab 3) to register with Selenium Grid Hub

  1.  Creating the Appium node configuration for the Tab 3 Device (appium_node_Tab3.json) using similar contents as shown below in the JSON file –

 

appium_node_Tab3.json
{
"capabilities":
     [
       {
          "deviceName": "3230e0d3d2d070dd",
         "version":"4.4.2",
         "maxInstances": 3,
         "platformName":"ANDROID"
       }
     ],
"configuration":
{
   "cleanUpCycle":2000,
   "timeout":30000,
   "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
   "host": "192.168.1.100",
   "port": 4724,
   "maxSession": 6,
   "register": true,
   "registerCycle": 5000,
   "hubPort": 4444,
   "hubHost": "127.0.0.1"
}
}

 

Note: devicename is one of the keys of the Appium node which we are configuring. Here the JSON describes that the Appium node will be associated with the S4 device and the device will be listening for commands coming on the Appium node server address (URL key in JSON) on port 4723.

 

On the other side, hubPort and hubHost parameters decide which port and host machine Selenium Grid is hosted on and in turn registers the Appium node with it.

 

2. Open Terminal and navigate to the location where Appium was installed. Run the following command to host the Appium node instance:

 

Appium.app/Contents/Resources/node_modules/appium/bin/appium.js –nodeconfig /Users/deranthika/Desktop/appium_node_Tab3.json -p 4724 -U 3230e0d3d2d070dd

Once this is up and running you will see the notification in the Selenium grid console as an Appium node is registered as shown below:

In the same way create the Appium node JSON configuration file for the S4 device as shown below and host another instance of the Appium node server –

 

appium_node_S4.json
{
"capabilities":
     [
       {
          "deviceName": "f68a5d03",
         "version":"5.0.1",
         "maxInstances": 3,
         "platformName":"ANDROID"
       }
     ],
"configuration":
{
   "cleanUpCycle":2000,
   "timeout":30000,
   "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
   "host": "192.168.1.100",
   "port": 4723,
   "maxSession": 6,
   "register": true,
   "registerCycle": 5000,
   "hubPort": 4444,
   "hubHost": "127.0.0.1"
}
}

 

Appium.app/Contents/Resources/node_modules/appium/bin/appium.js –nodeconfig /Users/deranthika/Desktop/appium_node_S4.json -p 4723 -U f68a5d03

Note: When hosting another instance of the Appium Node server for the S4 device we need to host it on a port other than the one that was used by the Appium server previously hosted for the Tab3 device i.e. 4724. So we choose 4723 as the port to host the Appium server for the S4 device. Always select a port from 4723 and above.

Step 3

Setting the Desired Capability in the Test Automation Script

 

Regardless of which programming language library we choose to write automation scripts, we need to set the desired capabilities for the Remote Webdriver.

Make sure you add the following code snippet in your before class.

 

Appium Node Server with Selenium Grid
@Before
    public void Androidsetup() throws MalformedURLException
    {
        DesiredCapabilities Androidcapability=new DesiredCapabilities();
            Androidcapability.setCapability("deviceName", "f68a5d03");
            Androidcapability.setCapability("platformName", "Android");
            Androidcapability.setCapability("platformVersion", "5.0.1");
            File file =new File("/Users/deranthika/MobileAPKs/Alfresco/Alfresco_v1.6_apkpure.com.apk");
            Androidcapability.setCapability("app", file.getAbsolutePath());
            androiddriver= new RemoteWebDriver(new URL("http://192.168.1.100:4723/wd/hub"),Androidcapability);
            DesiredCapabilities Androidcapability2=new DesiredCapabilities();
            Androidcapability2.setCapability("deviceName", "3230e0d3d2d070dd");
            Androidcapability2.setCapability("platformName", "Android");
            Androidcapability2.setCapability("platformVersion", "4.4.2");
            File file2 =new File("/Users/deranthika/MobileAPKs/Alfresco/Alfresco_v1.6_apkpure.com.apk");
            Androidcapability2.setCapability("app", file.getAbsolutePath());
            androiddriver= new RemoteWebDriver(new URL("http://192.168.1.100:4724/wd/hub"),Androidcapability2);
}

 

Now you would be able to run the tests on both the Tab3 and S4. Once you run the test and concluded you will see the following in the hub terminal which will show you the connections etc.

 

 

 

Configuring iOS device

Configure the Hub
Step 1
Download selenium server standalone jar to your computer

Step 2
Navigate to the location of  selenium server standalone located and run it as hub

daz:~ deranthika$ cd /Users/deranthika/Downloads
daz:Downloads deranthika$ java -jar selenium-server-standalone-2.48.2.jar -port 4444 -role hub
10:56:29.203 INFO - Launching Selenium Grid hub
2016-04-27 10:56:29.917:INFO::main: Logging initialized @1109ms

 

Configure Node
Step 1
Creating appium node configuration for iPad using json (create a json script as below and save in your computer eg: iOS.json)

{
  "capabilities":
  [
    {
      "browserName": "iPad"
    , "platform": "MAC"
    , "version": "9.1"
    "maxInstances": 1
    }
  ],
  "configuration":
  {
    "cleanUpCycle":2000,
    "timeout":30000,
    "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
    "host": "192.168.1.100",
    "port": 4723,
    "maxSession": 1,
    "register": true,
    "registerCycle": 5000,
    "hubPort": 4444,
    "hubHost": "127.0.0.1"
    }
}

Note: browserName is your device name and version is the iOS version of the device. You can get it both after connect iOS device to the computer. Then open xcode, Go the Window> Devices and select the device.

hub: your selenium hub url
url: appium doamin: port number
host: appium domain
port: appium port
hubPort: selenium hubport
hubHost: selenium hub host

Step 2
Run the node
To run node, you need to navigate to the location where appium installed. Then run below command

daz:Downloads deranthika$ cd /Applications/
daz:Applications deranthika$ Appium.app/Contents/Resources/node_modules/appium/bin/appium.js --nodeconfig /Users/deranthika/Desktop/ios.json -p 4723 -U c332fce71e40f09de19998dc763afea33d0a6b24

Where “/Users/deranthika/Desktop/ios.json” is ios.json saved location
-p 4723: appium port
-U c332fce71e40f09de19998dc763afea33d0a6b24: device UDID (You can get it the same way used to get device name and version)

 

If you able to run correctly you’ll be able to see below message

You can see configuration data on hub console

http://localhost:4444/grid/console

Set Desired Capabilities in Automation Script

@Before
    public void iOSsetup() throws MalformedURLException
    {  
        iOScapability.setCapability("platformName", "iOS");
        iOScapability.setCapability("platformVersion", "9.1");
        iOScapability.setCapability("deviceName", "iPad");
        iOScapability.setCapability("app", "com.zaizi.Sensefy");
        iOScapability.setCapability("udid", "c332fce71e40f09de19998dc763afea33d0a6b24");
        driver=new IOSDriver(new URL("http://192.168.1.100:4723/wd/hub"),iOScapability); 
    }

Then you can run the script as maven. And you don’t need to start appium server

Deleting a particular CSV file using Jmeter

You might come across situations where you will have to delete a document before running a process. Say you have a situation where you have to create a document with all the data in that is needed for the particular test. Every time you run the test you would need create new documents. For that case you would need to delete the previously created document. If that is the case how do you delete the document. Following is the way to do so.

  1. Initially Add a BeanShell PreProcessor in the start of the Thread if you need to Delete the document in the beginning of the Thread.Screen Shot 2016-04-11 at 11.24.58Screen Shot 2016-04-11 at 11.26.02
  2. Once you have added the Beanshell PreProcessor, now you can add the following script. to delete the document.Screen Shot 2016-04-11 at 11.47.52
    import java.text.*;
    import java.io.*;
    import java.util.*;
    downloadDoc = "download.csv";
    csvDir = vars.get("fileLocation");
    File file1 = new File( csvDir + downloadDoc);
    if (file1.exists()) {
    file1.delete(); 
    }

Now that the the Delete script is ready to be run and now you can delete the document you want to delete from the specific directory.

 

Randomly selecting values from .csv file for Jmeter Tests im on the

There might be instances where you will have to grab dynamic values from .csv file to run your Jmeter Performance tests. You can not use the CSV Data Config as the point here to select values randomly from the .csv file

The following script in a BeanShell PreProcessor will help to randomly select values from the CSV file that has the values. It randomly selects each row from the the CSV you can later break down the row as you prefer, in case a row has multiple values.

import java.text.*;
import java.io.*;
import java.util.*;

String [] params = Parameters.split(“,”);
csvTest = “download.csv”;
csvDir = vars.get(“fileLocation”);
ArrayList strList = new ArrayList();

try {
File file = new File( csvDir + csvTest);

if (!file.exists()) {
throw new Exception (“ERROR: file ” + csvTest + ” not found in ” + csvDir + ” directory.”);
}

BufferedReader bufRdr = new BufferedReader(new FileReader(file));
String line = null;

while((line = bufRdr.readLine()) != null) {
strList.add(line);
}

bufRdr.close();

Random rnd = new java.util.Random();
vars.put(“NodeId”,strList.get(rnd.nextInt(strList.size())));
//String NodeId= strList.get(rnd.nextInt(strList.size()));
//System.err.println(“Parts jjj “+q);
//String[] parts = q.split(“,”);

//System.err.println(“Parts 0 “+parts[0]);
//System.err.println(“NodeName “+parts[0]);
System.err.println(“NodeId “+NodeId);

//vars.put(“NodeId”,NodeId);
//String correctName = parts[0].replace(“%20″,””);
//vars.put(“name”,correctName);
}
catch (Exception ex) {
IsSuccess = false;
log.error(ex.getMessage());
System.err.println(ex.getMessage());
}
catch (Throwable thex) {
System.err.println(thex.getMessage());
}

Screen Shot 2016-04-08 at 11.14.15 AM (2).png

You can now use this scripts and randomly select values from CSV file when running your Jmeter Tests.

Uploading same document by renaming with Jmeter

Most of the time when we do performance testing we would require heavy data uploaded in the the system. When creating the data we would face issues where we might not be able to upload documents with duplicate names. How do we cater to this need.

The solution is quite simple. Rename the document every time you try to upload the document in that way the same document can be uploaded with different names.

  1. Create a Thread Group within a Test Plan. (You can name Thread Group as you wish)Screen Shot 2016-04-07 at 10.41.14
  2. Add a Loop Controller within the Thread Plan, and mention total amount of documents you would like to upload in the system with in the Loop Count as shown below.Screen Shot 2016-04-07 at 10.54.36
  3. Add two Counters one would have your the minimum value as the Start and the maximum value as Maximum. The other would have have the maximum value plus one as Maximum and minimum value as the Start. Mention the preferred Number Format and Increment. Reference Names for Counter1 and Counter2 should be given, as these names will be used for renaming.Screen Shot 2016-04-07 at 11.25.36   Screen Shot 2016-04-07 at 11.25.56
  4. Add the HTTP Request in the file data mention the loop_counter1 infront of the name of the document as shown below.Screen Shot 2016-04-07 at 12.11.48.pngMake sure that you have the initial or the minimum number mentioned in the name of the document in the Directory. Here the initial number we use 123000 as the Number Format is 123000.Screen Shot 2016-04-07 at 12.16.22.png
  5. Now Create the Script as shown below.Screen Shot 2016-04-07 at 12.31.19import java.text.*;
    import java.io.*;
    import java.util.*;
    //Take the fileLocation from the user defined variable
    fileLocation = vars.get(“fileLocation”);
    //Take the counter 1 value to indexNum
    indexNum = vars.get(“loop_counter”);
    //Take the counter 1 value to indexNum1
    indexNum1 = vars.get(“loop_counter1”);
    //The string portrays the current location of the document (with current name)
    mainFile = indexNum + “Download.ppt”;
    //The string portrays the location of the document which is renamed.
    fileName = indexNum1 + “Download.ppt”;
    //Get current document location
    File file = new File( fileLocation + mainFile);
    //Create location for renamed location
    File file2 = new File( fileLocation + fileName);
    //Rename document with the new location
     boolean success = file.renameTo(file2);
  6. Now you will be able to upload same document with different with the amount you need.
  7. Finally if you would like to rename the thread to the initial name you can run a BeanShell Sampler in the tear down Thread Group do the same scripting and rename the document.Screen Shot 2016-04-07 at 13.14.29.png