Selenium Grid Tutorial With Examples

Selenium Grid Tutorial

In the first tutorial of the Selenium Grid series, we learned the concept of the hub, node(s) and how to configure them. In this tutorial, we will implement the Selenium Grid on:

  • one node – one browser 
  • one node – multiple browsers, sequential execution (using @Paramteres(“value”) annotation) 
  • one node – multiple browsers, parallel execution (using @DataProvider annotation)
  • multiple nodes – multiple browsers, parallel execution

 

Tests should be executed using TestNG

 

 

Project Setup

 

From the previous post, configure the following:

  • Create a Java project Grid2add package seleniumgrid and create a new class SeleniumGridTest.
  • Only import the Selenium Standalone Server jar file.
  • Store the Selenium Standalone Server jar file and ChromeDriver/ GeckoDriver executable in the same folder.
  • configure a hub.
  • configure a node at port 5555 with chrome and firefox browsers, with 3 instances each. In case you want to use another physical machine as a node, replace the port number with the IP address of the target machine.

We will perform a login test on below demo application with various selenium grid configurations.

 

Selenium Grid Example
Login Page and After Login

 

 

One Node – One Browser

 

This is the basic Selenium Grid implementation where we will execute test scripts on one node and on one browser. Start your hub and nodes, if not already, and copy-paste the following code in eclipse.

 

package seleniumgrid;

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

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.Assert;
import org.testng.annotations.Test;

public class SeleniumGridTest {

    
    //TestNG annotation
    @Test
    public void testGrid() throws MalformedURLException {
        
        //ChromeOptions is used to manage options specific to ChromeDriver
        //Google for additional ChromeDriver specific options 
        ChromeOptions co = new ChromeOptions();
        co.addArguments("start-maximized");

        
        // RemoteWebDriver class is used to execute the tests on remote machines or nodes
        // RemoteWebDriver has multiple constructors
        RemoteWebDriver driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), co);
        
        //Navigate to the application
        driver.get("https://the-internet.herokuapp.com/login");
        driver.findElement(By.id("username")).sendKeys("tomsmith");
        driver.findElement(By.name("password")).sendKeys("SuperSecretPassword!");
        driver.findElement(By.xpath("//button[@type='submit']")).click();

        //Store the message displayed on the webpage after successful login
        WebElement successMsg = driver.findElement(By.xpath("//div[@id='flash']"));

        //Verify if above text is displayed
        Assert.assertTrue(successMsg.isDisplayed());

        driver.quit();
    }
}

 

Following is the code explanation:

  • @Test TestNG annotation is used to specify the testGrid() method, which we want to execute.
  • ChromeOptions class is used to configure ChromeDriver on the fly. Here we are maximizing the chrome browser upon invocation. THIS tutorial also makes use of the ChromeOptions class.
  • RemoteWebDriver class is used whenever tests need to be executed on a remote machine, or on a node (as in our case). This class has multiple constructors. The constructor which we are using accepts the hub URL and ChromeOptions object.
  • Next, open the demo application https://the-internet.herokuapp.com/login and log in using the credentials displayed on the screen.
  • Validate if the area highlighted in green color is displayed after a successful login using Assert.

 

Creating The testng.xml File

 

Let’s create a testngGrid.xml file to execute this test. Right click on the project folder > New > select XML File from the wizard pop up. Rename the file to testngGrid.xml. Copy and paste the following code to this XML file.

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
    <test name="Test">


        <classes>
            <class name="seleniumgrid.SeleniumGridTest" />
        </classes>
        
        
    </test>
</suite>

 

Visit the TestNG tutorial to understand more about this XML file. Right click on the file and select Run As -> TestNG Suite. Chrome browser should get launched, maximize, open the demo application, log in and quit. The test should get passed.

 

One Node – Multiple Browsers, Sequential Execution

 

Sequential test execution on multiple browsers means the execution on another browser starts only after the execution is finished on the current browser. This is not very useful, as we should execute multiple test scripts parallelly on different browsers, to be more efficient and productive.

@Parameters annotation of testng helps in test execution on multiple browsers.

Below is the updated code (highlighted) to execute tests on multiple browsers  sequentially:

 

package seleniumgrid;

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

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.Assert;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class SeleniumGridTest {

    //This annotation accepts the "name" value (browser) from testng.xml
    @Parameters("browser")
    //TestNG annotation
    @Test
    public void testGrid(String browse) throws MalformedURLException {
        
        
        ChromeOptions co = null;
        FirefoxOptions fo = null;
        RemoteWebDriver driver = null;
        System.out.println("Executing on "+browse);
        if(browse.equals("chrome")) {        
        
        //ChromeOptions is used to manage options specific to ChromeDriver
        //Google for additional ChromeDriver specific options 
        co = new ChromeOptions();
        co.addArguments("start-maximized");
        
        // RemoteWebDriver class is used to execute the tests on remote machines or nodes
        // RemoteWebDriver has multiple constructors
        
        //initiate the remote web driver with ChromeOptions reference
        driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), co);
        
        }else {
            
            //FirefoxOptions is same as ChromeOptions, but for firefox browser
            fo = new FirefoxOptions();
            //initiate the remote web driver with FirefoxOptions reference
            driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), fo);
            
        }
                
        
        //Navigate to the application
        driver.get("https://the-internet.herokuapp.com/login");
        driver.findElement(By.id("username")).sendKeys("tomsmith");
        driver.findElement(By.name("password")).sendKeys("SuperSecretPassword!");
        driver.findElement(By.xpath("//button[@type='submit']")).click();

        //Store the message displayed on the webpage after successful login
        WebElement successMsg = driver.findElement(By.xpath("//div[@id='flash']"));

        //Verify if above text is displayed
        Assert.assertTrue(successMsg.isDisplayed());

        driver.quit();
    }
}

 

The updated testng.xml file is:

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">

    <test name="TestChrome">
        <parameter name="browser" value="chrome"></parameter>

        <classes>
            <class name="seleniumgrid.SeleniumGridTest" />
        </classes>
    </test>
    
    <test name="TestFF">
        <parameter name="browser" value="firefox"></parameter>

        <classes>
            <class name="seleniumgrid.SeleniumGridTest" />
        </classes>
    </test>

</suite>

 

Below is the walkthrough of updated code:

testngGrid.xml:

  • 2 separate <test>, TestChrome and TestFF are created to handle execution on Chrome and Firefox browsers respectively.
  • Under each <test>, a <parameter name=” ” value=” “> tag is added. Here, name contains any user defined variable and value holds the actual value. In our scenario, browser is the name variable and chrome/ firefox are the actual values.

SeleniumGridTest.java

  • @Parameters tag is used to execute on multiple browsers. It accepts the name variable as a parameter.
  • Method name should also be updated to accept a String variable, which is the value of name variable.
  • ChromeOptions, FirefoxOptions, and RemoteWebDriver reference variables are initialized with null. 
  • if-else conditional block inflates the respective reference variable according to the called browser.

Right click on the testngGrid.xml and select Run As -> TestNG Suite. Execution on chrome should finish first, followed by the execution on firefox browser.

 

Selenium Grid sequential execution one node

 

 

One Node – Multiple Browsers, Parallel Execution

 

Above approach is not practical when we have a large number of test scripts. We can execute the test scripts in parallel on multiple browsers to reduce the execution time.

Parallel execution is not the property of selenium grid, but of TestNG. We will update the testngGrid.xml to achieve parallel execution. The updated code is written below:

 

package seleniumgrid;

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

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class SeleniumGridTest {

    //This annotation accepts the "name" value (browser) from testng.xml
    // @Parameters("browser")
    //TestNG annotation
    @Test(dataProvider = "getData")
    public void testGrid(String username, String password , String browse) throws MalformedURLException {
        
        
        ChromeOptions co = null;
        FirefoxOptions fo = null;
        RemoteWebDriver driver = null;
        
        System.out.println("Executing on "+browse);
        
        if(browse.equals("chrome")) {        
        
        //ChromeOptions is used to manage options specific to ChromeDriver
        //Google for additional ChromeDriver specific options 
        co = new ChromeOptions();
        co.addArguments("start-maximized");
        
        // RemoteWebDriver class is used to execute the tests on remote machines or nodes
        // RemoteWebDriver has multiple constructors
        
        //initiate the remote web driver with ChromeOptions reference
        driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), co);
        
        }else {
            
            //FirefoxOptions is same as ChromeOptions, but for firefox browser
            fo = new FirefoxOptions();
            //initiate the remote web driver with FirefoxOptions reference
            driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), fo);
            
        }
                
        
        //Navigate to the application
        driver.get("https://the-internet.herokuapp.com/login");
        driver.findElement(By.id("username")).sendKeys(username);
        driver.findElement(By.name("password")).sendKeys(password);
        driver.findElement(By.xpath("//button[@type='submit']")).click();

        //Store the message displayed on the webpage after successful login
        WebElement successMsg = driver.findElement(By.xpath("//div[@id='flash']"));

        //Verify if above text is displayed
        Assert.assertTrue(successMsg.isDisplayed());

        driver.quit();
    }
    
    @DataProvider(parallel=true)
    public Object[][] getData() {

        Object data[][] = new Object[2][3];

        data[0][0] = "tomsmith";
        data[0][1] = "SuperSecretPassword!";
        data[0][2] = "chrome";

        data[1][0] = "tomsmith";
        data[1][1] = "SuperSecretPassword!";
        data[1][2] = "firefox";
        
        return data;

    }
}

 

  • Method getData() is created to hold the test data and browser information.
  • This method is a type of Object, which is a parent class of all Object types.
  • The size of Object array is determined by the test data and the number of browsers. Here the size is [2][3] since there are two browsers and three test data(username, password, and type of browser).
  • @Test annotation is used to bind the data provider with the test.
  • Test method arguments are also updated to hold the values passed from the getData() method.
  • Removing parallel=true from the @DataProvider would result in sequential execution.

Also, the updated testngGrid.xml is:

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="tests" thread-count="2">

    <test name="gridTest">
        <classes>
            <class name="seleniumgrid.SeleniumGridTest" />
        </classes>
    </test>
    
    <!-- <test name="TestChrome"> <parameter name="browser" value="chrome"></parameter> 
        <classes> <class name="seleniumgrid.SeleniumGridTest" /> </classes> </test> 
        <test name="TestFF"> <parameter name="browser" value="firefox"></parameter> 
        <classes> <class name="seleniumgrid.SeleniumGridTest" /> </classes> </test> -->

</suite>

 

Update the <suite> tag with parallel = “tests”. thread-count limits the simultaneous execution to the provided value.

Execute the above XML, both chrome and firefox browsers should open in parallel.

 

Multiple Nodes – Multiple Browsers, Parallel Execution

 

We can create another node by changing the port number to the node command. Below command creates a second node on the same machine with port number 6666. Browser should be firefox and maxInstances=1

Remember to open the command prompt inside the folder where Selenium Standalone Server jar is saved.

 

java -jar selenium-server-standalone-3.141.59.jar -role webdriver -hub http://localhost:4444/grid/register -port 6666 -browser browserName=firefox,maxInstances=1

 

Stop the other node and update the command for port 5555 to run on chrome browser with maxInstances=1.

Once you execute the above commands, refresh the console window in the browser, 2 nodes should get displayed with the desired configuration.

 

Selenium Grid with multiple nodes

 

Execute the test script and it should start the test execution on both the nodes parallelly, on respective browsers.

Create multiple @Test and try to execute on multiple nodes. Comment below if you have any query.

Author: Dhawal Joshi

A post-graduate in MCA, ISTQB & ITIL certified QA with more than 8 years of experience in QA working with a CMMI Level 5 organization as System Analyst. I started my automation journey with HP UFT(formerly known as QTP) and for the past few years, I am using Selenium for automation. I also have experience in Android Application Development, Java, HTML, and VBScript. When I am not working, I like to spend time with my family, cooking and learning new developments in IT.

Leave a Reply

Your email address will not be published. Required fields are marked *