In recent years there has been increase in the growth of mobile applications across different business verticals. Most organizations are targeting to convert their user base into app users and as such there is an increase in mobile app development across platforms with android and iOS being the most popular choice.

With this increasing trend of mobile application development comes the bigger challenge of testing the mobile app to cover all customer scenarios as well as business use cases. Testing a mobile app poses its own set of challenges some of the common ones being:

  1. Testing on various models and various versions of the OSes to ensure the app is working correctly on all supported platforms and devices
  2. Frequent release cycles which demands such a testing is repeated very often

The best possible way to solve this challenge is to automate the tests as much as possible and let the nightly builds certify all the app changes.

Coming to automation of mobile apps there are some tools available in the market some are open source and free while others are paid and licensed. Choosing the right tool is critical to the success and business needs of the organization. The most popular mobile app automation tool is Appium for a number of reasons like multiple language bindings, support for android iOS and windows which are the popular platforms, extensive community support over the internet and it’s free for use. In this article I will explain how we can achieve parallel testing across multiple android and iOS devices using appium and selenium grid.

Setting up the grid

Download the latest Selenium server from selenium website (mine was 3.141.59)

Run the jar in hub mode:

java -jar /path/to/selenium-server-standalone.jar -role hub -port 4444

That’s pretty much it for running the grid. If you are going to run grid on a separate host make note of the host machine IP or URL to be used later. If you plan to run other appium nodes on the same machine as the grid then localhost should be fine. Lets define our HUB_URL as:

HUB_URL = "http://localhost:4444/wd/hub" or "http://<grid host IP>:4444/wd/hub" (for appium java client version 7.6.0)

Now initialize the AppiumDriver with this HUB_URL like so:

AppiumDriver appiumDriver = new AppiumDriver<>(new URL(HUB_URL), capabilities); 

Now with our grid in place we can register as many mobile devices with this grid as we want.

Creating the json file

In order to register a device with the grid we need to create a node config file which is a json file. A sample json file for android app configuration looks like the following:

node.json
{
    "capabilities":
    [{
        "maxInstances": 1,
        "browserName" : "ANDROID",
        "automationName": "UiAutomator2",
        "platform": "ANDROID"
    }
    ],
    "configuration": {
        "cleanUpCycle": 2000,
        "timeout": 30000,
        "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
        "maxSession": 1,
        "register": true,
        "registerCycle": 5000,
        "host" : "<ip of your machine>",
        "port" : "<appium port eg 4723>",
        "url" : "http://<ip of your machine>:<appium port>/wd/hub",
        "hubPort": "4444",
        "hubHost": "<ip of grid host>"
    }
}

We can create as many node config files as the number of devices we want to register with the grid. Please make sure all the node config files have different values for the appium port.

Register devices with the grid

Now we register the device with the grid by running appium server on separate ports for each device. For android device we run the command like this:

appium -p 4723 --nodeconfig node.json --relaxed-security --default-capabilities '{"udid":"<udid>","systemPort" : <port eg. 8200>}'

udid is the device id of each device and systemPort is the unique port for each device starting from 8200 for androoid devices and 8100 for iOS devices.

For iOS its very similar:

appium -p 4724 --nodeconfig node.json --relaxed-security --default-capabilities '{"udid":"<udid>","wdaLocalPort" : <port eg. 8100>}'

Here we use the capability wdaLocalPort for iOS instead of systemPort that we use for android.

That’s all we need from the setup side.

Running tests in parallel from the client

Now to actually see parallelism in action we need to invoke the tests to run in parallel. Different build tools have different ways of doing this. If using maven we can use surefire plugin and configure parallelism like this:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <configuration>
    <parallel>methods</parallel>
    <threadCount>4</threadCount>
  </configuration>
</plugin>

This will execute test methods within test classes in four parallel threads. The number of thread count should match with the number of devices registered with the grid.

If using gradle we can use maxParallelForks switch to specify the number of threads for execution like this:

test {
    maxParallelForks = 2
}

Here parallelism is always at test class level and will execute two test classes in parallel. Again the number of parallel forks should match the number of devices registered with the grid.

That’s all folks. Hope you like it! Happy testing!