Data Driven Selenium Web Test with TestNG in Java

This tutorial covers creating a data driven web test with Selenium WebDriver for Java that scrapes and verifies the results of DuckDuckGo search engine using TestNG testing framework in Visual Studio Code.

This tutorial already assumes you have Selenium WebDriver installed and configured on Visual Studio Code. See this tutorial for setting up Selenium WebDriver for Java on Visual Studio Code.

Test Code

The test code is purposely compact and doesn’t contain any details about DuckDuckGo’s site. That’s because all of that layout logic is encompassed in a DuckDuckGo Page Object Model class. This makes the tests more maintainable in case the layout of the site changes in the future. It also allows other tests in other test classes to reuse the same page object model, with no need for duplication.

There are two tests, both data driven with multiple test cases. The first test checks the top domain on the results page against an expected domain. The second test checks the top three domains for a variety of search terms.

We use @BeforeSuite annotation to initialize the WebDriver since it’s only going to be executed once before the test suite is run. We useĀ @BeforeTest annotation to reset DuckDuckGo to its default state before every test so a test isn’t influenced by results from the previous test. TestNG DataProviders are used to setup the search terms and expected domains in the result page.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import java.util.List;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

import org.testng.Assert;
import org.testng.annotations.*;

public class DuckDuckGoTests {
  DuckDuckGoPOM duckDuckGoPOM;
  WebDriver webDriver;

  @BeforeSuite
  public void setUpOnce() {
    System.setProperty("webdriver.chrome.driver", "/Users/misha/dev/selenium/bin/chromedriver");
    webDriver = new ChromeDriver();
    duckDuckGoPOM = new DuckDuckGoPOM(webDriver);
  }

  @BeforeTest
  public void setUp() {
    duckDuckGoPOM.reset();
  }
 
  @DataProvider(name = "searches1")
  public Object [][] dataTopDomain() {
    return new Object [][] {
      new Object [] { "hello world", "https://helloworld.com" },
      new Object [] { "test automation", "https://www.testim.io" },
      new Object [] { "best beaches in the world", "https://travel.usnews.com" },
    };
  }

  @DataProvider(name = "searches2")
  public Object [][] dataTop3Domains() {
    return new Object [][] {
      new Object [] { "hello world",               new String [] { "https://helloworld.com", "https://www.imdb.com", "https://en.wikipedia.org"} },
      new Object [] { "test automation",           new String [] { "https://www.testim.io", "https://www.atlassian.com", "https://www.guru99.com"} },
      new Object [] { "best beaches in the world", new String [] { "https://travel.usnews.com", "https://www.tripadvisor.com", "https://www.cnn.com" } },
    };
  }
 
  @Test(dataProvider = "searches1")
  public void testTopDomain(String pSearchString, String pExpectedFirstDomain) {
    List searchResults = duckDuckGoPOM.search(pSearchString);
    Assert.assertEquals(searchResults.get(0), pExpectedFirstDomain);
  }

  @Test(dataProvider = "searches2")
  public void testTop3Domains(String pSearchString, String [] pExpectedTop3Domains) {
    List searchResults = duckDuckGoPOM.search(pSearchString);
    Assert.assertEquals(searchResults.get(0), pExpectedTop3Domains[0]);
    Assert.assertEquals(searchResults.get(1), pExpectedTop3Domains[1]);
    Assert.assertEquals(searchResults.get(2), pExpectedTop3Domains[2]);
  }
}

 

Duck Duck Go Page Object Model

To make the tests as small as possible and to decouple the physical layout of the web page from the test, we created a DuckDuckGo Page Object Model (DuckDuckGoPOM.java) that models the behaviors that we need for our test. Specifically:

  • searching for any term
  • collecting a list of domains from the results page
  • resetting the search engine to a default state

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import java.util.ArrayList;
import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class DuckDuckGoPOM {
  WebDriver webDriver;
  private static final String DDG = "https://duckduckgo.com/";
  public DuckDuckGoPOM(WebDriver pWebDriver) {
    webDriver = pWebDriver;
  }

  /**
   *
   * @param pSearch Search string to use
   * @return A list of domains in the order they appear on the results page
   */

  public List search(String pSearch) {
    webDriver.get(DDG);
    WebElement ddgInputWebElement = webDriver.findElement(By.xpath("//*[@id="search_form_input_homepage"]"));
    CharSequence keysToSendCharSequence = new StringBuffer(pSearch);
    ddgInputWebElement.sendKeys(keysToSendCharSequence);

    webDriver.findElement(By.id("search_button_homepage")).click();

    List  resultURLsWebElements = webDriver.findElements(By.className("result__url__domain"));
    List resultList = new ArrayList();
    for(WebElement resultWebElement : resultURLsWebElements) {
      System.out.println("adding element text: " + resultWebElement.getText());
      resultList.add(resultWebElement.getText());
    }
    return resultList;
  }

  public void reset() {
    webDriver.get(DDG);
  }
}

Running the TestNG Tests in Visual Studio Code

Visual Studio Code has built in support for JUnit and TestNG tests. A new standalone Java project was created (named “Project1”) and all the Selenium jars were added as well as TestNG to support writing and running tests. TestNG jars were downloaded from Maven’s central repository for TestNG.

Running the tests through Visual Studio Code was done from the Testing tab (first arrow) which allows us to run all the Selenium tests at once or separately (second arrow) and get a nice report with the results (on the right).