Parallel Execution on different Mobile Platforms
Tags: seleniumgrid, android, ios, parallelexecution
Published: 2022-02-06 21:32:57

In order to facilitate parallel execution across various mobile devices of same or different platforms we will be using appium with Selenium Grid. Selenium Grid is basically a proxy server that speaks the WebDriver protocol, and manages connections to a pool of WebDriver servers. It wasn't designed specifically to work with Appium, but because Appium also speaks the WebDriver protocol (and because we taught Appium how to register with Selenium Grid)

Architectural Diagram

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0jnrtcw9hhsioqpxfbuo.JPG)

Details Steps:
*  ***Step 1:Set up Selenium Server in Hub Mode***<br/>
      Need to download Selenium-Standalone-Server and start it as hub mode in certain host or port.
      ```java
      java -jar selenium-server-standalone-2.53.0.jar -role hub -host 192.168.3.172 -port 4444
      ```
*  ***Step 2:Start Appium Servers in Node Mode***<br/>
      We can register any number of appium servers in node mode.

      * ***Appium Node 1: Android Node***
      ```java
      appium -a 192.168.3.172 -p 4723 --nodeconfig android_nodeconfig.json --chromedriver-executable "chromedriver.exe"
      ```
      Details of **android_nodeconfig.json**
```json
{
    "capabilities": [
        {
            "deviceName": "ZY224P7HZB",
            "browserName": "chrome",
            "version":"9",
            "maxInstances": 2,
            "platformName": "Android"
        }
    ],
    
"configuration": {
        "cleanUpCycle":3000,
        "timeout":30000,
        "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
        "maxSession": 2,
        "register": true,
        "registerCycle": 5000,
        "hubPort": 4444,
        "hubHost": "192.168.3.172"
    }
}

```
  * ***Appium Node 2: iOS Node***
```java
          appium -a 192.168.5.122  -p 4733 --nodeconfig iOS_nodeconfig.json
```
Details of iOS_nodeconfig.json:
```json
  {
      "capabilities": [
          {
              "deviceName": "iPad mini 3",
              "browserName": "Safari",
              "version":"12.1",
              "maxInstances": 2,
              "platformName": "i0S",
              "automationName": "XCUITest",
              "xcodeOrgId" : "",
              "xcodeSigningId" : "iPhone Developer",
          }
      ],

  "configuration": {
          "cleanUpCycle":3000,
          "timeout":30000,
          "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
          "maxSession": 2,
          "register": true,
          "registerCycle": 5000,
          "hubPort": 4444,
          "hubHost": "192.168.3.172"
      }
  }

```
*  ***Step 3:The testNgConfig File***<br/>
```xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="Suite 1" parallel="tests" thread-count="2">
        <!-- For sequential run use only platform parameter for both (iOS & Android) test cases-->
       <parameter name="hubUrl" value="http://192.168.3.117:4444/wd/hub"></parameter>
        <test name="Android_VerifiyNotifications1">
            <parameter name="deviceName" value="ZY224P7HZB" />
            <parameter name="platformVersion" value="9" />
            <parameter name="platform" value="Android" />
            <parameter name="browserName" value="chrome"/>
            <classes>
                <class name="com.basics.MobileParallelExecutionScript"/>
            </classes>
        </test>

        <test name="iOS_Execution">
            <parameter name="deviceName" value="iPad mini 3" />
            <parameter name="platformVersion" value="12.1" />
            <parameter name="platform" value="iOS" />
            <parameter name="browserName" value="Safari"/>
            <classes>
                <class name="com.basics.MobileParallelExecutionScript"/>
            </classes>
        </test>

    </suite>
```
*  ***Step 3:Java Class***<br/>
```java

        import io.appium.java_client.ios.IOSDriver;
        import io.appium.java_client.remote.MobileCapabilityType;
        import org.openqa.selenium.By;
        import org.openqa.selenium.remote.DesiredCapabilities;
        import org.openqa.selenium.remote.RemoteWebDriver;
        import org.testng.annotations.Parameters;
        import org.testng.annotations.Test;

        import java.net.MalformedURLException;
        import java.net.URL;

        public class MobileParallelExecutionScript {

            @Test
            @Parameters({"deviceName","platformVersion","platform","browserName","hubUrl"})
            public void test1(String deviceName,String platformVersion,String platformName, String browserName,String hubUrl) throws    MalformedURLException, InterruptedException {

                DesiredCapabilities caps = new DesiredCapabilities();
                caps.setCapability("platformName", platformName);
                caps.setCapability("deviceName", deviceName);
                caps.setCapability("browserName",browserName);
                caps.setCapability("platformVersion",platformVersion);
                caps.setCapability("noReset",true);
                //String url = "http://" + "192.168.3.140" + ":" + "4444" + "/wd/hub";
                String url=hubUrl;
                if(platformName.equalsIgnoreCase("Android")){
                    RemoteWebDriver driver=new RemoteWebDriver(new URL(url),caps);
                    driver.get("https://www.amazon.in/");
                    //driver.findElement(By.xpath("//span[text()='Fresh']")).click();
                    Thread.sleep(7000);
                    driver.quit();
                }else{
                    caps.setCapability(MobileCapabilityType.AUTOMATION_NAME,"XCUITEST");
                    caps.setCapability("xcodeSigningId", "iPhone Developer");
                    caps.setCapability("xcodeOrgId","3WS698JC32");
                    caps.setCapability(MobileCapabilityType.UDID,"bd21c102521b9dc2837ca16c530669006db71f1b");
                    caps.setCapability(MobileCapabilityType.BROWSER_NAME, "Safari");
                    caps.setCapability("startIWDP",true);
                    IOSDriver driver_ios=new IOSDriver(new URL(url),caps);
                    driver_ios.startRecordingScreen();
                    driver_ios.get("https://www.amazon.in/");
                    //driver_ios.findElement(By.xpath("//a[text()='Best Sellers']")).click();
                    Thread.sleep(7000);
                    driver_ios.stopRecordingScreen();
                    driver_ios.quit();
                }


            }

        }

```
*  ***Step 5:Video Browsing***<br/>


For Android, we can use Vysor Plugin of Chrome.

For iOS, we can perform driver.startRecording, and then open the address ip:9100 of the iOS node machine.