DEV Community

Cover image for Parameterization In TestNG – DataProvider and TestNG XML (With Examples)
himanshuseth004 for LambdaTest

Posted on • Edited on • Originally published at lambdatest.com

Parameterization In TestNG – DataProvider and TestNG XML (With Examples)

Test automation, or automation testing as it’s called popularly, is not as easy as it sounds. All permutations and combinations of all possible user interactions have to be considered and based on that you would have to create a test script to validate your web application over numerous browsers + OS combination. This is where Parameterization plays a pivotal role in Selenium automation testing. In this TestNG tutorial, I will show you how to perform parameterization in TestNG for Selenium automation testing.

Why Do We Parameterize?

In the real world for web UI testing, we expect our website or web application to work correctly with varied inputs and it is practically not possible to validate our scenarios with just a single data set. So we ensure that our application is functioning as expected when exposed to different data sets or different combinations for browsers and OS. Multiple test combinations mean multiple input values.

Now, you cannot hardcode test values every time in your test automation scripts, otherwise making one change will require you to edit many test automation scripts. That’s where Parameterization in TestNG or any other comes into the picture and the reason why we parameterize our Selenium automation testing scripts is to provide different data sets to our web application at runtime.

Get started with this complete Selenium automation testing tutorial. Learn what Selenium is, its architecture, advantages and more for automated cross browser testing.

How Do We Perform Parameterization? And Why Use TestNG?

If your application involves inputting different types of user interactions, then Parameterization is the way to go. We can parameterize our automation scripts as per the framework being used for example Parameterization in TestNG framework for Selenium automation testing. We can consider using excel files to fetch data sets and subsequently use it in our automation scripts but as we enhance our automation suite, it becomes necessary to use more robust test automation frameworks like TestNG to cover a wide category of tests in a more powerful manner. In this post, we will be focussing mainly on Parameterization in TestNG, what ways can it be achieved in TestNG and how do we go about writing these parameters in our Selenium automation testing scripts. Let us first begin with understanding the different types of Parameterization in TestNG and how can we achieve the same.

Types of Parameterization in TestNG

So primarily we can achieve parameterization in TestNG in two ways.

  1. Using “Parameters annotation” and TestNG XML file.
  2. Using “DataProvider annotation”.

Parameterization In TestNG Using @Parameters Annotation & XML file

Let us first see the simple syntax of writing parameter annotation in our class:

@Parameter({“parameter name”})

Note that we can use more than one parameter as well in our annotation which can be written as below:
@Parameters({“param1”,”param2”,”param3”})

As of now, Parameters have been scoped to only Suite or Test tag in testng.xml file. If the same parameter value is passed in both Suite and Test, the priority is given to parameter value passed in the Test tag.

Before we go ahead with examples of parameterization, we need to understand what good would be using Parameterization in TestNG do to our Selenium automation testing activities. Consider a scenario of searching for certain keywords in a search engine like Google. We would have to write the same lines of code for each keyword to get different results and that is not a feasible approach. This is where Parameterization in TestNG or any other test automation framework for Selenium comes into the picture. Using Parameterization in TestNG, you can pass these keywords as different parameters in a testng.xml and add @parameters annotation in the Selenium automation testing suite. Let us see it by example.

Scenario: Open google.com in your browser and search 3 keywords separately

To complete this scenario, here are the detailed steps that our script has to perform:

  1. Launch the browser and open www.google.com
  2. Add the first keyword as input in the search box and hit search.
  3. Verify the input value on UI to be same as from test data.
  4. Repeat the above two steps for the other 2 keywords.

1.PNG

Below code shows how we can do it without parameterization in TestNG.


package parameterization;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.Test;
public class WithoutParameter {
        WebDriver driver;
        @Test
        public void noParam(){
            //Declaring our first keyword
            String keyWord="Selenium";
            //Initializing Driver
            System.setProperty("webdriver.gecko.driver", "C:\\geckodriver.exe");
            driver = new FirefoxDriver();
            driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS);
            //Opening search engine
            driver.get("https://google.com");
            //Finding search text box  
             WebElement searchBox = driver.findElement(By.name("q"));
             //Sending keyword value
             searchBox.sendKeys(keyWord);
             System.out.println("The search keyword entered is : " +keyWord);    
             //Verifying the keyword on UI
             Assert.assertTrue(searchBox.getAttribute("value").equalsIgnoreCase(keyWord));
             driver.quit();
        } 
}
Enter fullscreen mode Exit fullscreen mode

In order to pass the other 2 keywords, we’ll have to write the same piece of code again with different keyword values for the string ‘ keyWord ’, which would result in a lengthy and repetitive code. And, in the future, if you have to test for more values of keywords, you would have to write more tests.

Let us now simplify our problem bypassing these keywords as parameters in our testng.xml and adding @parameters annotation in our test.

Java Code:


package parameterization;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class ParameterizedClass {
WebDriver driver;   
        @Parameters("keyWord")
        @Test
        public void Parameterpassing(String keyWord){   
            //Initializing Driver
//Mention the path to your local webdriver
            System.setProperty("webdriver.chrome.driver", "D:\\LocalDriver\\chromedriver.exe");
            driver = new ChromeDriver();
            driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS);
            //Opening search engine
            driver.get("https://google.com");
            //Finding search text box  
             WebElement searchBox = driver.findElement(By.name("q"));
             //Sending keyword value
             searchBox.sendKeys(keyWord);
             System.out.println("The search keyword entered is : " +keyWord);    
             //Verifying the keyword on UI
             Assert.assertTrue(searchBox.getAttribute("value").equalsIgnoreCase(keyWord));
             driver.quit();
        }
}
Enter fullscreen mode Exit fullscreen mode

Here is the TestNG.xml that will be used to perform parameterization in TestNG for Selenium automation testing.


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite thread-count="3" parallel="tests"  name="suite">
  <test name="demo1" >
      <parameter name="keyWord" value="Selenium" />
      <classes>
      <class name="com.lambdatest.ParameterizedClass"/>
    </classes>
  </test> <!-- Test -->
   <test name="demo2" >
    <parameter name="keyWord" value="LambdaTest" />
    <classes>
      <class name="com.lambdatest.ParameterizedClass"/>
    </classes>
  </test> <!-- Test -->
    <parameter name="keyWord" value="Browser Testing" />
    <test name="demo3" >
    <classes>
      <class name="com.lambdatest.ParameterizedClass"/>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->
Enter fullscreen mode Exit fullscreen mode

You can now run this test to check that our parameter value is being passed to our test method and hence desired results are obtained. You can run this by following the steps below:

Step 1: Right-click on the testng.xml file in the project explorer and click on Run as:

testngxml

Step 2: Select Run as TestNG Suite and you can see the emailable report or summary to view the results.

demo

So the next time we have to run the same test for different test value, instead of copy pasting the same piece of code in multiple files, we just have to edit the .xml file, included more values and run the suite. That’s it. That is how effective and time saving your Selenium automation testing can become by leveraging parameterization in TestNG.

Through this usability testing tutorial, you will learn how usability testing is a great way to discover unexpected bugs, find what is unnecessary or unused before going any further, and have unbiased opinions from an outsider.

Would Parameterization In TestNG Help Us With Automated Browser Testing?

By far in this TestNG tutorial for parameterization, you may have realized the importance of Parameters with the example explained in the previous section. Now, you may already be thinking of a way to incorporate parameterization in TestNG scripts for automated browser testing. Let me help you kickstart that with a very common scenario where we need to execute our tests on multiple browsers, let us see how we can leverage parameters to perform automated browser testing.

Scenario: Printing a specific browser value by passing the browser name as a parameter.

Java Code:


package parameterization;
 import org.testng.annotations.Test;
 import org.testng.annotations.Parameters;
 public class ParameterPass {

  @Parameters("browser")
  @Test
  public void test1(String browser) {
          if(browser.equalsIgnoreCase("FF"))
            {
              System.out.println("The browser value is : " +browser);
            }else if(browser.equalsIgnoreCase("Chrome"))
            {
                    System.out.println("The browser value is : " +browser);

            }else if(browser.equalsIgnoreCase("IE"))
            {
                    System.out.println("The browser value is : " +browser);
            }
            else
            {
                    System.out.println("Incorrect browser value passed.");
            }    
  }
}
Enter fullscreen mode Exit fullscreen mode

Testng.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
  <test name="Firefox Test">
   <parameter name="browser" value="FF"/>
    <classes>
    <class name="parameterization.ParameterPass"/>
    </classes>
  </test>

  <test name="IE Test">
   <parameter name="browser" value="IE"/>
    <classes>
    <class name="parameterization.ParameterPass"/>
    </classes>
  </test>
  <test name="Incorrect Browser">
  <parameter name="browser" value="XYZ"/>
    <classes>
    <class name="parameterization.ParameterPass"/>
    </classes>
  </test>
 </suite>
Enter fullscreen mode Exit fullscreen mode

On running the above testng xml, you’ll see the below output in console:

testNGxml1

If you go by the detailed results, you’ll see that the parameter values passed in the XML is also printed in the test results summary:

resultxml

The emailable report shows the different parameters passed to the different tests hence making it easier to consolidate the results:

parameterspassed

IEtest

Let us now try passing 2 parameters to our test to understand how we can leverage combinations of parameters for Selenium automation testing. Make note that whatever number of parameters you pass to your test, you need to accept the same number of parameters in your test method that too in correct sequence.

Scenario: Printing a specific browser & URL value by passing the browser name as well as the URL as a parameter.

package parameterization;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class ParameterPass_Multiple {

    @Parameters({"url","browser"})
    @Test
    public void test1(String url,String browser)
    {
        if(browser.equalsIgnoreCase("FF"))
        {
                System.out.println("The browser value is : " +browser);
        }
        else if(browser.equalsIgnoreCase("Chrome"))
        {   
                System.out.println("The browser value is : " +browser);     
        }
        else if(browser.equalsIgnoreCase("IE"))
        {
                System.out.println("The browser value is : " +browser);
        }
        else
        {
                System.out.println("Incorrect browser value passed.");
        }
Enter fullscreen mode Exit fullscreen mode

}
}


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
  <test name="Firefox Test">
   <parameter name="url" value="http://www.google.com"/>
   <parameter name="browser" value="FF"/>
    <classes>
    <class name="parameterization.ParameterPass_Multiple"/>
    </classes>
  </test>

  <test name="Chrome Test">
   <parameter name="url" value="http://www.yahoo.com"/>
   <parameter name="browser" value="Chrome"/>
    <classes>
    <class name="parameterization.ParameterPass_Multiple"/>
    </classes>
  </test>
</suite>
Enter fullscreen mode Exit fullscreen mode

Now on running the above xml below output is generated which prints both the parameters that were passed:

testngcases

testreport

Email Report:

Email Report

Parameterization In TestNG For An Online Selenium Grid

Parameterization is a neat way to build yourself a neat Test Driven Testing framework using TestNG. It’s up to you how you want to leverage different types of parameterization in TestNG or even both at the same time if the use case requires it.

The next question to answer would be, whether parameterization in TestNG works with an online Selenium Grid of 2000+ real browsers, offered by LambdaTest?

Yes, it does! In fact, parameterization in TestNG or any other framework is considered as one of the best ways to run tests in parallel on multiple different test environments, especially if you have to regularly change the test environments to test on.

For example, let’s take a scenario where you have a test that you want to run on multiple test environments to ensure that the webpage is cross browser compatible. It’s a typical example of automated cross browser testing that is now a primary requirement for nearly every organization that generates any business through the web.

To run the test on LambdaTest Selenium Grid, you need to define the desired capabilities object, that instructs our online Selenium Grid about which environments you need to run your test on. To achieve this, you can parameterize the values for the desired capabilities object. For example, consider the following code. It’s a simple script that opens up a todo list and performs some actions. This same script is being run at multiple environments by parameterizing the desired capabilities environment values in XML file.

package com.lambdatest;

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

import org.openqa.selenium.By;
//import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.Assert;
//import org.testng.annotations.AfterSuite;
import org.testng.annotations.Parameters;
import org.testng.annotations.AfterTest;
//import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

public class TestNGTodo4 {

    private RemoteWebDriver driver;
    private String Status="failed";

    @BeforeTest
    @Parameters({ "os", "browser", "version", "build" })
    public void setup( String os, String browser, String version, String build) throws MalformedURLException {
        String username = "mudits";
        String authkey = "kIVQzcwYkSMgZFWoSMxQjcR3ASJo2BIOUQ97GmTwdnPEOFEO2b";
        String hub = "@hub.lambdatest.com/wd/hub";

        DesiredCapabilities caps = new DesiredCapabilities();
        caps.setCapability("platform", os);
        caps.setCapability("browserName", browser);
        caps.setCapability("version", version);
        caps.setCapability("build", build);
        caps.setCapability("name", "TestNG-Todo-Script-4");
        caps.setCapability("network", true);
        caps.setCapability("visual", true);
        caps.setCapability("video", true);
        caps.setCapability("console", true);

        driver = new RemoteWebDriver(new URL("https://" + username + ":" + authkey + hub), caps);
    }

    @Test
    public void basicTest() throws InterruptedException {
        String spanText;
        System.out.println("Loading Url");
        driver.get("https://4dvanceboy.github.io/lambdatest/todo.html");


        System.out.println("Checking Box");
        driver.findElement(By.name("todo-1")).click();


        System.out.println("Checking Another Box");
        driver.findElement(By.name("todo-2")).click();


        System.out.println("Checking Box");
        driver.findElement(By.name("todo-3")).click();


        System.out.println("Checking Another Box");
        driver.findElement(By.name("todo-4")).click();


        driver.findElement(By.id("todotext")).sendKeys(" List Item 6");
        driver.findElement(By.id("addbutton")).click();


        driver.findElement(By.id("todotext")).sendKeys(" List Item 7");
        driver.findElement(By.id("addbutton")).click();


        driver.findElement(By.id("todotext")).sendKeys(" List Item 8");
        driver.findElement(By.id("addbutton")).click();




        System.out.println("Entering Text");
        driver.findElement(By.id("todotext")).sendKeys("Get Taste of Lambda and Stick to It");


        driver.findElement(By.id("addbutton")).click();

        System.out.println("Checking Another Box");
        driver.findElement(By.name("todo-9")).click();

        // Let's also assert that the todo we added is present in the list.

        spanText = driver.findElementByXPath("/html/body/div/div/div/ul/li[9]/span").getText();
        Assert.assertEquals("Get Taste of Lambda and Stick to It", spanText);
        Status="passed";
        //Thread.sleep(150);

        System.out.println("TestFinished");

    }

    @AfterTest
    public void tearDown() {
        driver.executeScript("lambda-status=" + Status);
        System.out.println(this.getClass().getName());
        driver.quit();
    }

}

Here’s the Corresponding XML file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite thread-count="3" parallel="tests"  name="suite">
  <parameter name="build" value="Demo-TestNG" />
  <test name="demo1" >
      <parameter name="os" value="windows 10" />
      <parameter name="browser" value="chrome" />
      <parameter name="version" value="73" />
      <classes>
      <class name="com.lambdatest.TestNGTodo4"/>
    </classes>
  </test> <!-- Test -->
   <test name="demo2" >
    <parameter name="os" value="windows 8.1" />
    <parameter name="browser" value="firefox" />
    <parameter name="version" value="59" />
    <classes>
      <class name="com.lambdatest.TestNGTodo5"/>
    </classes>
  </test> <!-- Test -->
    <parameter name="os" value="macOS Mojave" />
    <parameter name="browser" value="safari" />
    <parameter name="version" value="12" />
    <test name="demo3" >
    <classes>
      <class name="com.lambdatest.TestNGTodo6"/>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->
Enter fullscreen mode Exit fullscreen mode

Did you notice how I used the thread-count and parallel value in the Suite tag for Selenium automation testing?

This above script will run the same test class on 3 different environments and the best part, they would be run in parallel. That means that all three tests would execute at the same time cutting down your test execution time by multiple folds. Thanks to Selenium Grid for allowing us to leverage parallel testing with Selenium.

In this System testing tutorial, learn why System testing is important and all the intricacies of the System testing process.

Things to consider

After attending this TestNG tutorial, this far, you must be feeling confident and maybe a little thrilled about using Parameters into your next project for Selenium automation testing but hold your horses for a little while. There are a few points that have to be taken care of while using @Parameters annotation.

⟶ If you try to typecast the parameter value in testng.xml to a corresponding test method parameter, an error would be thrown. Example, if you have given the method parameter as an integer , but you pass a String value in the TestNG.xml, you’ll get an exception as below:

testngxmla

Testng.xml:

testNG_xml

Use of @Optional annotation

If the parameter that we defined in our method is not present in testng.xml then a testNG exception would come up and our test would skip. To overcome this situation, we can use @Optional annotation. Let us first have a look at the syntax for this:

@Parameter(“browser”)
@Test
public void paramCheck(@Optional(“OptionalParameter”) String val)   { …. }
Enter fullscreen mode Exit fullscreen mode

Let us understand this in-depth with an example in this TestNG tutorial.

Java Code:


package parameterization;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class optionalParameter {    
        @Parameters("Param One")
        @Test
        public void testOptionOne(String firstParam){
            System.out.println("The first parameter is : " +firstParam);
        }

        @Parameters("Param Two")
        @Test
        public void testOptionTwo(@Optional("OptionalParameter")String secondParam){
            System.out.println("The second parameter is : " +secondParam);
        }   
}
Enter fullscreen mode Exit fullscreen mode

Testng.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<parameter name="Param One" value="My First Parameter"/>
<parameter name="Param Two" value="My Second Parameter"/>
  <test name="Test">
    <classes>
    <class name="parameterization.optionalParameter"/>
    </classes>
  </test>
Enter fullscreen mode Exit fullscreen mode

On running the above testng.xml, we’ll get simple results wherein the first and second parameter will be displayed since both have been explicitly declared in the XML. The same is shown in the below output images.

Let us now comment on the second parameter from the xml and see how the @Optional Annotation works:

New testng.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<parameter name="Param One" value="My First Parameter"/>
<!-- <parameter name="Param Two" value="My Second Parameter"/> -->
  <test name="Test">
    <classes>
    <class name="parameterization.optionalParameter"/>
    </classes>
  </test>
</suite>
Enter fullscreen mode Exit fullscreen mode

On running this new XML we see that the Optional parameter in TestNG was declared in the test method being printed now and no exception is thrown anywhere:

⟶ There may be scenarios where you need to test multiple values of a parameter using testng.xml. @Parameters annotation doesn’t serve the purpose. We can have a number of parameters, but each of these can have a single value, making our code reusable. It serves more like a configuration file for our project. For you to use multiple values for a parameter Data Providers comes to the rescue.

The next section of this TestNG tutorial will talk more about Data Providers and their usage in Selenium automation testing.

In this Appium tutorial, learn about Appium automation and its benefits for mobile automation testing.

Parameterization In TestNG Using Data Providers

In the section above, we have seen how can we use the @Parameters annotation in our framework to get various results. Now, as we proceed we will come across cases where we will have to use test scripts against multiple sets of data. We might need huge data sets to be used in a single execution. This type of testing is also called Data Driven Testing which can be achieved conveniently by @DataProvider annotation in our TestNG framework.

Let us now first see the syntax for @DataProvider annotation.

@DataProvider(name=”testData”)
Enter fullscreen mode Exit fullscreen mode

You need to note two points before we start using it for parameterization in TestNG, first, @DataProvider has only one attribute, ‘ name ’. Second, it is optional and in case you do not specify it , then the name would be the same as the corresponding method name.

This Data Provider returns a 2-Dimensional array object.

Let us try to understand this with a simple example where we try to pass the monument and city name using data provider. You can further use this example as a base to login to Gmail or Facebook using different email ID and passwords.

Scenario: Open google.com in your browser and search 3 keyword combinations separately.

Following would be the steps to get this executed:

  1. Launch the browser to open www.google.com
  2. Search the first keyword combination.
  3. Get the page title.
  4. Repeat the steps above, i.e. 2 & 3 for the other 2 keywords combination.

2.PNG

In this tutorial on Agile testing, let’s deep dive into the history of Agile testing, its advantages, disadvantages, methods, quadrants, and best practices.

Java Code:


package dataProvider;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class Data_Provider {

      WebDriver driver;

  @Test(dataProvider="searchText") 
  public void paramByDataProvider(String monument,String city) throws InterruptedException {
    //Initializing Driver
            System.setProperty("webdriver.gecko.driver", "C:\\geckodriver.exe");
            driver = new FirefoxDriver();
            //Opening search engine
            driver.get("https://google.com");
     WebElement searchBox=driver.findElement(By.name("q"));
     searchBox.sendKeys(monument +" "+city);
     System.out.println("You are trying to search " +monument+ " which is in " +city);

     WebElement srchBtn = driver.findElement(By.name("btnK"));
     srchBtn.submit();
     Thread.sleep(3000);
     System.out.println("The page title is: " +driver.getTitle());
      driver.quit();
  }


  /*Data Provider which returns Object[][] wherein
   *  first column has 'monument' and the second one has 'city'
   **/

  @DataProvider(name="searchText")
  public Object[][] getDataProviderData(){
            Object[][] searchWords=new Object[3][2];
            //Enter data into Object Array
            searchWords[0][0]="India Gate";
            searchWords[0][1]="Delhi";
            searchWords[1][0]="Taj Mahal";
            searchWords[1][1]="Agra";
            searchWords[2][0]="Char Minar";
            searchWords[2][1]="Hyderabad";
      return searchWords;

  }
} 
Enter fullscreen mode Exit fullscreen mode

To run the above code we use below TestNG.xml and run our test the same like we have been doing in the examples above:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
  <test name="Firefox Test">
    <classes>
    <class name="parameterization.Data_provider"/>
    </classes>
  </test>
 </suite> <!-- Suite -->
Enter fullscreen mode Exit fullscreen mode

We’d receive the output like below which summarizes the data providers passed and the corresponding results:

testngreport

Emailable report:

Emailable report

Emailable report

In the example above, we tried with data providers being invoked from the same class. You can also invoke data providers from another class by simply making the data provider method static and providing the data provider class in the test method annotation. Let’s see the same example by creating a different class for our data provider.

Java Code for Data Provider Class:


package dataProvider;
import org.testng.annotations.DataProvider;
 public class DataProviderClass {
    @DataProvider(name="searchText")
      public static Object[][] getDataProviderData(){
                Object[][] searchWords=new Object[3][2];
                //Enter data into Object Array
                searchWords[0][0]="India Gate";
                searchWords[0][1]="Delhi";
                searchWords[1][0]="Taj Mahal";
                searchWords[1][1]="Agra";
                searchWords[2][0]="Char Minar";
                searchWords[2][1]="Hyderabad";
              return searchWords;
              }
}
Enter fullscreen mode Exit fullscreen mode

Java Code for the Class from where Data Provider is called:


package dataProvider;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.Test;
 public class ClassLevelDataProvider {
          WebDriver driver;
 @Test(dataProvider="searchText",dataProviderClass=DataProviderClass.class) 
public void paramByDataProvider(String monument,String city) throws InterruptedException {
    //Initializing Driver
            System.setProperty("webdriver.gecko.driver", "C:\\geckodriver.exe");
            driver = new FirefoxDriver();
            //Opening search engine
            driver.get("https://google.com");
     WebElement searchBox=driver.findElement(By.name("q"));
     searchBox.sendKeys(monument +" "+city);
     System.out.println("You are trying to search " +monument+ " which is in " +city);

     WebElement srchBtn = driver.findElement(By.name("btnK"));
     srchBtn.submit();
     Thread.sleep(3000);
     System.out.println("The page title is: " +driver.getTitle());
      driver.quit();
}
}
Enter fullscreen mode Exit fullscreen mode

TestNG.xml to run the above code:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
  <test name="Firefox Test">
    <classes>
    <class name="parameterization.ClassLevelDataProvider"/>
    </classes>
  </test>
  </suite> <!-- Suite -->
Enter fullscreen mode Exit fullscreen mode

On running you can see for yourself that we receive the same results as we did before. To understand a bit more about the various conditions that we might face in our automation it is important to understand a few more examples of using the Data Provider annotation with parameters viz Method and ITestContext.

Example 1 – Using Method Parameter in TestNG

What if we want the same data provider to work differently for different methods like in a case where we test different data sets for different test methods, we will use method parameters in TestNG. Let us see through an example that will follow the steps below:

  • Check if method name is domesticMonuments
  • If it is then return one set of value
  • If not then another set of value

Java Code:

package dataProvider;
import java.lang.reflect.Method;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class dataProviders {
        WebDriver driver;
    @BeforeMethod
    public void setUp(){
            //Initializing Driver
                        System.setProperty("webdriver.gecko.driver", "C:\\geckodriver.exe");
                        driver = new FirefoxDriver();
                        //Opening search engine
                        driver.get("https://google.com");
                }
    @AfterMethod
    public void tearDown(){
            driver.quit();
    }
    @Test(dataProvider="destinations")
    public void domesticMonuments(String monument,String city) throws InterruptedException{
            WebElement searchBox=driver.findElement(By.name("q"));
             searchBox.sendKeys(monument +" "+city);
             System.out.println("You are trying to search " +monument+ " which is in " +city); 
             WebElement srchBtn = driver.findElement(By.name("btnK"));
             srchBtn.submit();
             Thread.sleep(3000);
             System.out.println("The page title is: " +driver.getTitle());
                }
    @Test(dataProvider="destinations")
    public void intlDestinations(String location) throws InterruptedException{
            WebElement searchBox=driver.findElement(By.name("q"));
            searchBox.sendKeys(location);
            System.out.println("You are trying to search : " +location);
            WebElement srchBtn = driver.findElement(By.name("btnK"));
             srchBtn.submit();
             Thread.sleep(3000);
             System.out.println("The page title is: " +driver.getTitle());   
    }
    @DataProvider(name="destinations")
      public Object[][] getDataProviderData(Method m){
            if(m.getName().equalsIgnoreCase("domesticMonuments")){
                return new Object[][]{
                        { "India Gate", "Delhi" },
                        { "Taj Mahal", "Agra" },
                        { "Char Minar", "Hyderabad" }
                };
                }
            else{
                return new Object[][]{
                        {"Paris"},
                        {"Cairo"},
                        {"Washington"}
                };
            }    
      }
}
Enter fullscreen mode Exit fullscreen mode

Testng.XML to run the above code:

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






The results on running the xml would be like below, wherein you will be able to see the details of the data providers used.

Example 2 – Using ITestContext Parameter in TestNG

Suppose my test methods are assigned to different groups and I need to use different test data for different groups. In such a scenario we can use ITestContext parameter with our Data Provider annotation. Let us see an example of the same.

Java Code:

package dataProvider;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.ITestContext;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class ITestContext_DP {
    WebDriver driver;
    @BeforeMethod(groups={"One","Two"})
    public void setUp(){
            //Initializing Driver
                        System.setProperty("webdriver.gecko.driver", "C:\\geckodriver.exe");
                        driver = new FirefoxDriver();
                        //Opening search engine
                        driver.get("https://google.com");
                }
    @AfterMethod(groups={"One","Two"})
    public void tearDown(){
            driver.quit();
    }

    @Test(dataProvider="searchKey" , groups="One")
    public void testMethodOne(String monument,String city) throws InterruptedException{
            WebElement searchBox=driver.findElement(By.name("q"));
             searchBox.sendKeys(monument +" "+city);
             System.out.println("You are trying to search " +monument+ " which is in " +city);

             WebElement srchBtn = driver.findElement(By.name("btnK"));
             srchBtn.submit();
             Thread.sleep(3000);
             System.out.println("The page title is: " +driver.getTitle());
    }   
    @Test(dataProvider="searchKey" , groups="Two")
    public void testMethodTwo(String location) throws InterruptedException{

            WebElement searchBox=driver.findElement(By.name("q"));
            searchBox.sendKeys(location);
            System.out.println("You are trying to search : " +location);
            WebElement srchBtn = driver.findElement(By.name("btnK"));
             srchBtn.submit();
             Thread.sleep(3000);
             System.out.println("The page title is: " +driver.getTitle());   
    }
    @DataProvider(name="searchKey")
      public Object[][] getDataProviderData(ITestContext c){
            Object[][] grpArr = null;
            for (String grp : c.getIncludedGroups()){
                if(grp.equalsIgnoreCase("One")){
                        grpArr = new Object[][]{
                            { "India Gate", "Delhi" },
                            { "Taj Mahal", "Agra" },
                            { "Char Minar", "Hyderabad" }
                        };
                        break;
                }
                else if(grp.equalsIgnoreCase("Two")){
                        grpArr = new Object[][]{
                            {"Paris"},
                            {"Cairo"},
                            {"Washington"}
                        };
                }
            }   
            return grpArr; 
      }
}
Enter fullscreen mode Exit fullscreen mode

To call this testNG class, you can use below xml which would run the two test sets based on different groups.

Testng.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" >
  <test name="First DP Run">
    <groups>
        <run>
            <include name = "One" />
        </run>
    </groups>
    <classes>
    <class name="dataProvider.ITestContext_DP"/>
    </classes>
  </test>
  <test name="Second DP Run">
    <groups>
        <run>
            <include name = "Two" />
        </run>
    </groups>
    <classes>
    <class name="dataProvider.ITestContext_DP"/>
    </classes>
  </test> 
 </suite>
Enter fullscreen mode Exit fullscreen mode

Running the above xml would yield results like below:

Run Appium mobile testing of native and web apps. Improve your app quality with instant access to real devices on LambdaTest. Register now.

Conclusion

Parameterization in TestNG allows you to perform data-driven testing in a more efficient manner. By declaring parameters, you won’t have to write multiple test automation scripts for different test inputs of a single test suite, making it easier for you to maintain your test automation code. I hope this TestNG tutorial has helped you to leverage your Selenium automation testing scripts. Parameterization in TestNG for your Selenium automation testing scripts can be done using either the DataProvider or the Parameter annotation with TestNG.xml. We talked about parameterizing in both ways with examples, in great-detail. We realized that DataProvider further offers 2 parameters i.e. Method & ITestContext. You can now fire up your test automation scripts using parameterization in TestNG for your next project. Let me know your thoughts about this TestNG tutorial in the comment section below. In case you have any doubts or queries feel free to post them as well. Cheers and happy testing!

Top comments (0)