Selenium Grid console page

Selenium Grid for Appium mobile automation

Often we wanted to perform mobile execution in parallel. The best way of performing the parallel execution is through selenium grid. I’ve faced few issues while setting up the grid for appium. I’ll share my learnings about setting up the grid for appium mobile automation. 

Pre-requisites

  • Download selenium standalone server jar file – At the time of writing, the version of latest selenium is 2.53.
  • Appium – The version that I was using is 1.4.16 and installed as Node npm package. I recommend to you also use npm package.
  • Atleast two android devices for this experiment.

Setup the selenium grid

Place the downloaded selenium standalone server jar in some directory. In my case I’ve placed in /Users/<username>/Tools/selenium.

Open your terminal and navigate to the directory to where you placed the jar file and execute the following command:

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

This will start the selenium grid server in your local ip with the default port of 4444. After you see this message Selenium Grid hub is up and running, open your browser and hit the following url:
http://<your ip>:4444/grid/console and you should be able to see the following in your browser:

Selenium Grid console page

Congratulations!!! You started your grid successfully. Let’s setup the nodes for our mobile devices.

Setup the Appium nodes

I’ve two devices with me now, samsung S4 and samsung S5. I’m going to setup grid nodes for these two devices.

As per the documentation of appium here, we need a node config json file to hook our appium node to our selenium grid hub. Let’s prepare our 1st node config json and I’m calling that as node_s4.json:

{
    "capabilities": [
        {
            "applicationName": "Samsung S4",
            "browserName": "Samsung S4",
            "platformName": "ANDROID",
            "maxInstances": 1
        }
    ],
    "configuration": {
        "cleanUpCycle": 2000,
        "timeout": 30000,
        "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
        "host": "127.0.0.1",
        "port": 4723,
        "maxSession": 1,
        "register": true,
        "registerCycle": 5000,
        "hubPort": 4444,
        "hubHost": "192.168.0.198"
    }
}

Here applicationName is mandatory since the grid identifies to which appium node the job should b e routed. Also, make sure you change the hubHost to your ip address.

Now let’s start our appium node with this node config. In your terminal, start your appium like this:

appium --nodeconfig /Users/<<username>>/Tools/selenium/node_s4.json -p 4723 -bp 4724 -U <<s4 device id>>

This will start the appium server on the port 4723 and the bootstrap port 4724 (remember, the bootstrap port is mandatory for android devices) and with the device id of your device which you can get from adb devices.

Now refresh your grid console in your browser and you should see this:

Grid console with S4 device

Do the same for another device. In my case, the node json for samsung S5 device will look like:

{
    "capabilities": [
        {
            "applicationName": "Samsung S5",
            "browserName": "Samsung S5",
            "platformName": "ANDROID",
            "maxInstances": 1
        }
    ],
    "configuration": {
        "cleanUpCycle": 2000,
        "timeout": 30000,
        "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
        "host": "127.0.0.1",
        "port": 4730,
        "maxSession": 1,
        "register": true,
        "registerCycle": 5000,
        "hubPort": 4444,
        "hubHost": "<<your ip>>"
    }
}

Changed the applicationName, browserName and port of appium node, and saved the file as node_s5.json. Now start your 2nd appium node in another terminal like this:

appium --nodeconfig /Users/<<username>>/Tools/selenium/node_s5.json -p 4730 -bp 4731 -U <<s5 device id>>

Refresh your browser and you should see this in your grid console page:

Grid console with S5

Voila!!! We have two appium nodes connected to our selenium hub.

In your test now, add the applicationName as part of your desired capabilities and point to the grid url instead of appium url. For example, my DesiredCapabilities and driver instantiation would look like:

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("deviceName", "Android");
capabilities.setCapability("applicationName", "Samsung S4");
capabilities.setCapability("app", "ApiDemos-debug.apk");
capabilities.setCapability("appPackage", "io.appium.android.apis");
capabilities.setCapability("appWaitActivity", "io.appium.android.apis.ApiDemos");
capabilities.setCapability("noReset", true);

driver = new AndroidDriver(new URL("http://<your ip>:4444/wd/hub/"), capabilities);

This will execute tests on Samsung S4 device.

Mistakes done and Lessons learnt

  1. applicationName – I spent more time on solving this issue. I was using dataProvider to execute tests in parallel. Even I was having 2 nodes setup, always grid was routing my tests to one node only. This was the haunting problem. Make sure you have this applicationName in your capabilities. The selenium default capability matcher explains about this. Follow this blog for more information: Rationale Emotions.
  2. nodeconfig – Even though you start your appium from the same directory where you placed the node config json files, you should provide the absolute path of the node config json for the parameter –nodeconfig while starting your appium server.
  3. UDID – Make sure you start your appium server with the -U parameter with your device id in case you have more than one device. The reason is appium always selects the first device in your device list.

There will be a followup post on how I performed parallel execution using this grid setup. Coming Soon!!!

21 Replies to “Selenium Grid for Appium mobile automation”

  1. my script is working on only one node i also using applicationName my json as
    {

    "capabilities": [{
            "applicationName": "5.0.2Android",
            "browserName": "5.0.2Android",
            "version": "5.0.2",
            "maxInstance": 1,
            "platform": "ANDROID"
    
        }
    
    ],
    
    "configuration":
    
    {
    
        "nodeTimeout": 120,
    
        "port": 4725,
    
        "hubPort": 4444,
    
        "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
    
        "hubHost": "10.2.10.45",
        "host": "127.0 .0 .1",
        "role": "node",
    
        "nodePolling": 2000,
    
        "register": true,
    
        "registerCycle": 1000,
    
        "cleanUpCycle": 2000,
    
        "timeout": 30000,
    
        "masSession": 1
    
    }
    

    }

    1. Why do you want to do that? But to answer your question you can simply use ProcessBuilder to run your selenium server as hub and use AppiumDriverLocalService to create node at run time. But I’m against on doing this, since I prefer my hub and nodes should be running always.

      1. Thanks for your answer. I want to run my tests cycle with one click so I can run it over and over again with maven. When I run the hub and nodes manually, all devices run on first cycle but on the second one only one device run. So I need to close the hub and all nodes and rerun them again on every new cycle.

        1. You can pretty much do it with Java. But I prefer to do this using shell script. And I hook my shell script into Jenkins as pre build script.

    1. I don’t have any script ready with me since I’ve never came across the situation where I’ve to run things using script. A simple maven based jenkins job is itself keeping me happy to run my tests. I would recommend you to try out and reach out to me for any help in case you are stuck at any specific point.

  2. Hey Vimal,

    Thanks a ton for detailed info, I was struck for 2 days with this issue and it solved.

    You’re my hero of the day 🙂

    Regards,
    Vikram

  3. Hi Vimal,

    can you please clarify “…I was using dataProvider to execute tests in parallel….”. I’m trying to run tests in parallel with help maven surefire / failsafe plugin but no success yet.

    Thanks & Regards,
    Vikram

  4. HI Vimal,

    I have to execute parallel test on mobile browser
    This is how I started appium node
    {
    “capabilities”: [
    {
    “applicationName”: “Lenovo K4 Note”,
    “browserName”: “Lenovo K4 Note”,
    “platformName”: “ANDROID”,
    “maxInstances”: 1
    }
    ],
    “configuration”: {
    “cleanUpCycle”: 2000,
    “timeout”: 30000,
    “proxy”: “org.openqa.grid.selenium.proxy.DefaultRemoteProxy”,
    “host”: “127.0.0.1”,
    “port”: 4757,
    “maxSession”: 1,
    “register”: true,
    “registerCycle”: 5000,
    “hubPort”: 4444,
    “hubHost”: “10.98.13.204”
    }
    }

    here is driver initialization code

    AppiumDriver appiumDriver ;
    DesiredCapabilities capabilities = new DesiredCapabilities();
    capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, “Android”);
    capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, “Android”);
    capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, “Lenovo K4 Note”);
    // capabilities.setCapability(MobileCapabilityType.”noReset”, true);
    capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, “Lenovo K4 Note”);

            try {
                 appiumDriver = new AndroidDriver(new URL("http://10.98.13.204:4444/wd/hub"), capabilities);
            } catch (Exception e) {
            System.out.println("Error while trying to initialize android Driver");
            e.printStackTrace();
            }   
    

    attached node to selenium grid using
    appium –nodeconfig C:\Users\dmore\Desktop\selenium\appium_nodes\lenovo_k4_note.json -p 4757 -bp 4758 -U 10.98.4.37:5555

    Giving below error

    org.openqa.selenium.SessionNotCreatedException: A new session could not be created. (Original error: No app set; either start appium with –app or pass in an ‘app’ value in desired capabilities, or set androidPackage to launch pre-existing app on device) (WARNING: The server did not provide any stacktrace information)
    Command duration or timeout: 175 milliseconds
    Build info: version: ‘2.46.0’, revision: ’87c69e2′, time: ‘2015-06-04 16:16:47’
    System info: host: ‘MTO37914GU1376C’, ip: ‘10.98.13.204’, os.name: ‘Windows 7’, os.arch: ‘amd64’, os.version: ‘6.1’, java.version: ‘1.8.0_102’
    Driver info: io.appium.java_client.android.AndroidDriver

    1. In your DesiredCapabilities, you are passing an automationName. It should be applicationName.
      Next, there is not browser called Lenovo K4 note. The browser name should either be chrome if you want to automate on chrome browser or just browser if native browser. Make sure you change this in you desired capabilities and node capabilities.

  5. Hi guys!, Thanks for the post.

    I wish to generate the reports using this setup with Extent Reports and TestNG but I am unable to do so.
    Could you explain the setup if we wish to do that?.
    Thanks in advance.

  6. Hey Vimal,

    this is not working with current version of appium server and selenium server 3.4.0

    can you please clarify if this still working for you and if yes which version of appium & selenium are you using ?

    Thanks,
    Vikrma

Leave a Reply