TestNG Selenium Integration Example
In this article, I am going to show you an example of TestNG and Selenium integration. Let me first brief you on TestNG and Selenium.
TestNG is an annotation based testing framework which allows you to create configurable test suites where each suite contains one or more tests. A test in turn is composed of one more test classes.
Selenium is used in automating web applications for testing purposes. Unlike HtmlUnit, it uses actual browser to execute its tests.
Let’s start with the setup:
- Since the example is about TestNG and Selenium integration, we will simplify our setup by using Maven as our build tool.
- TestNG Maven Project Example will guide you on how to setup a Maven based project and run the TestNG tests.
- Our examples will be based on Chrome and Firefox, so make sure both are installed in your machine.
- The browser drivers will be automatically downloaded as a result of the dependencies being added to the maven project file
pom.xml
. - In case of chrome, we also need to download chromedriver.exe. This acts as a bridge between chrome and the driver.
- I have used Eclipse as the IDE, version Luna 4.4.1.
1. TestNG and Selenium Dependencies
Since our project is dependent on TestNG and selenium, we need to add their dependencies in Maven’s pom.xml
file. For TestNG, we need to add org.testng
package and for selenium, we need to add org.seleniumhq.selenium
. Once saved, it will download Selenium 2.0 java client library and all its dependencies.
pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javacodegeeks.testng.spring</groupId> <artifactId>testNGSpring</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>2.45.0</version> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.8.8</version> <scope>test</scope> </dependency> </dependencies> <properties> <spring.version>4.1.5.RELEASE</spring.version> </properties> </project>
2. TestNG Selenium Simple Search Example
Selenium provides WebDriver
as its API for automating web application testing. WebDriver
drives the browser directly using each browser’s built-in support for automation.
In this example, we will use the WebDriver
to open google and search for TestNG.
WebDriver
is an interface so we still need to an implementation to run the test on an actual browser. We will select the implementation based on the browser used. For example, if we are using firefox, we will use FirefoxDriver
. If it is chrome, we will use ChromeDriver
. Since ChromeDriver
works with Chrome through the chromedriver.exe, we need to make sure that the binary be placed somewhere on your system’s path.
Points to be noted regarding the test class:
- In
@BeforeSuite
method,initDriver()
, we create the driver. searchTestNGInGoogle()
is our test method.- We call
driver.navigate().to(url)
to open the url. - Once the site is open, we need to get a handle on the search field so that we can type in the text to be searched.
- When we call
driver.findElement(By.name("q"))
, theWebDriver
locates the search field using matching name attribute. - Next, we call
element.sendKeys("TestNG")
to type in the text “TestNG” in the search field. - The search is submitted on calling
element.submit().
- Finally, we wait for the results to be returned.
- In
@AfterSuite
method,quitDriver()
, we calldriver.quit()
to close the browser session.
TestNGSeleniumSimpleSearchExample:
package com.javacodegeeks.testng.selenium; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; public class TestNGSeleniumSimpleSearchExample { private WebDriver driver; @BeforeSuite public void initDriver() throws Exception { System.out.println("You are testing in firefox"); driver = new FirefoxDriver(); } @Test public void searchTestNGInGoogle() { final String searchKey = "TestNG"; System.out.println("Search " + searchKey + " in google"); driver.navigate().to("http://www.google.com"); WebElement element = driver.findElement(By.name("q")); System.out.println("Enter " + searchKey); element.sendKeys(searchKey); System.out.println("submit"); element.submit(); (new WebDriverWait(driver, 10)).until(new ExpectedCondition() { public Boolean apply(WebDriver d) { return d.getTitle().toLowerCase() .startsWith(searchKey.toLowerCase()); } }); System.out.println("Got " + searchKey + " results"); } @AfterSuite public void quitDriver() throws Exception { driver.quit(); } }
testngSimpleSearch.xml:
<?xml version="1.0" encoding="UTF-8"?> <suite name="TestNgSeleniumSuite" parallel="false"> <test name="TestNgSeleniumTest"> <classes> <class name="com.javacodegeeks.testng.selenium.TestNGSeleniumSimpleSearchExample" /> </classes> </test> </suite>
Output:
[TestNG] Running: C:\javacodegeeks_ws\testNGSelenium\src\test\resources\com\javacodegeeks\testng\selenium\testngSimpleSearch.xml You are testing in firefox Search TestNG in google Enter TestNG submit Got TestNG results =============================================== TestNgSeleniumSuite Total tests run: 1, Failures: 0, Skips: 0 ===============================================
3. WebDriver Injection using spring
Instead of creating the WebDriver ourselves, we can inject the implementation using the spring’s dependency injection. Here we will modify our previous example by using spring to inject the driver.
Since we are going to rely on spring, we need to add spring-context
and spring-test
to our dependencies in pom.xml
.
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javacodegeeks.testng.spring</groupId> <artifactId>testNGSpring</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>2.45.0</version> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.8.8</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency> </dependencies> <properties> <spring.version>4.1.5.RELEASE</spring.version> </properties> </project>
The below context file contains the driver bean definition. The class
attribute points to org.openqa.selenium.firefox.FirefoxDriver
.
driver_context.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <bean id="driver" class="org.openqa.selenium.firefox.FirefoxDriver" /> </beans>
The below test class, does exactly what the previous one did, the only change is that the driver is injected through spring’s annotation @ContextConfiguration
. Its value contains the location path to the context file driver_context.xml
. The driver member is anootated with @Autowired
so that the spring can inject the implementation.
Since we are going to rely on TestNG-spring integration framework, test class TestNGSeleniumDriverInjectionExample
extends AbstractTestNGSpringContextTests
.
TestNGSeleniumDriverInjectionExample:
package com.javacodegeeks.testng.selenium; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @ContextConfiguration("driver_context.xml") public class TestNGSeleniumDriverInjectionExample extends AbstractTestNGSpringContextTests { @Autowired private WebDriver driver; @BeforeClass public void printBrowserUsed() { System.out.println("Driver used is: " + driver); } @Test public void searchTestNGInGoogle() { final String searchKey = "TestNG"; System.out.println("Search " + searchKey + " in google"); driver.navigate().to("http://www.google.com"); WebElement element = driver.findElement(By.name("q")); System.out.println("Enter " + searchKey); element.sendKeys(searchKey); System.out.println("submit"); element.submit(); (new WebDriverWait(driver, 10)).until(new ExpectedCondition() { public Boolean apply(WebDriver d) { return d.getTitle().toLowerCase() .startsWith(searchKey.toLowerCase()); } }); System.out.println("Got " + searchKey + " results"); } @AfterSuite public void quitDriver() throws Exception { driver.quit(); } }
testngDriverInjection.xml:
<?xml version="1.0" encoding="UTF-8"?> <suite name="TestNgSeleniumSuite" parallel="false"> <test name="TestNgSeleniumTest"> <classes> <class name="com.javacodegeeks.testng.selenium.TestNGSeleniumDriverInjectionExample" /> </classes> </test> </suite>
Output:
[TestNG] Running: C:\javacodegeeks_ws\testNGSelenium\src\test\resources\com\javacodegeeks\testng\selenium\testngDriverInjection.xml Driver used is: FirefoxDriver: firefox on WINDOWS (441cda6b-9e73-4594-b4e8-7134a1623c7d) Search TestNG in google Enter TestNG submit Got TestNG results =============================================== TestNgSeleniumSuite Total tests run: 1, Failures: 0, Skips: 0 ===============================================
4. TestNG Selenium Data-Driven Testing Example
Suppose we want to do multiple searches in google by using our search method, we would want to pass in different search strings each time we call the method. In this example, I will demonstrate data-driven testing to do multiple searches in google.
We will modify our example further and introduce a parameter to our search method. Since we will be searching multiple times, we will keep the search method name generic, call it searchGoogle()
. We will provide the data using a @DataProvider
method called searchStrings()
which returns “TestNG” and “Selenium” as the search keywords. The @Test
annotation is modified to include searchGoogle
as the dataProvider
.
TestNGSeleniumDataDrivenSearchExample:
package com.javacodegeeks.testng.selenium; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @ContextConfiguration("driver_context.xml") public class TestNGSeleniumDataDrivenSearchExample extends AbstractTestNGSpringContextTests { private WebDriver driver; @BeforeClass public void printBrowserUsed() { System.out.println("Driver used is: " + driver); } @Test(dataProvider = "searchStrings") public void searchGoogle(final String searchKey) { System.out.println("Search " + searchKey + " in google"); driver.navigate().to("http://www.google.com"); WebElement element = driver.findElement(By.name("q")); System.out.println("Enter " + searchKey); element.sendKeys(searchKey); System.out.println("submit"); element.submit(); (new WebDriverWait(driver, 10)).until(new ExpectedCondition() { public Boolean apply(WebDriver d) { return d.getTitle().toLowerCase() .startsWith(searchKey.toLowerCase()); } }); System.out.println("Got " + searchKey + " results"); } @DataProvider private Object[][] searchStrings() { return new Object[][] { { "TestNG" }, { "Selenium" } }; } @AfterSuite public void quitDriver() throws Exception { driver.quit(); } }
testngDataDrivenSearch.xml:
<?xml version="1.0" encoding="UTF-8"?> <suite name="TestNgSeleniumSuite" parallel="false"> <parameter name="browser" value="chrome"></parameter> <parameter name="driverPath" value="c://selenium/chromedriver.exe"></parameter> <test name="TestNgSeleniumTest"> <classes> <class name="com.javacodegeeks.testng.selenium.TestNGSeleniumDataDrivenSearchExample" /> </classes> </test> </suite>
Now when we run the test, it runs twice, once for “TestNG” and then for “Selenium”.
Output:
[TestNG] Running: C:\javacodegeeks_ws\testNGSelenium\src\test\resources\com\javacodegeeks\testng\selenium\testngDataDrivenSearch.xml Driver used is: FirefoxDriver: firefox on WINDOWS (ab3f6869-6669-4ccf-8e8f-9479f35aa790) Search TestNG in google Enter TestNG submit Got TestNG results Search Selenium in google Enter Selenium submit Got Selenium results =============================================== TestNgSeleniumSuite Total tests run: 2, Failures: 0, Skips: 0 ===============================================
5. TestNG Selenium Multiple Browser Example
Now suppose, we want to run our test on multiple browsers, all we need to do is parameterize our initDriver()
method and pass it the name of the browser on which we want to run our test.
Based on the browser, we will create either ChromeDriver
or FirefixDriver
. We will pass the browser name through testng.xml
.
TestNGSeleniumBrowserCfgExample:
package com.javacodegeeks.testng.selenium; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; public class TestNGSeleniumBrowserCfgExample { private WebDriver driver; @Parameters({"browser", "driverPath"}) @BeforeTest public void initDriver(String browser, @Optional("") String driverPath) throws Exception { System.out.println("You are testing on browser " + browser); browser = browser.toLowerCase(); if (!driverPath.equals("")) { System.setProperty("webdriver.chrome.driver", driverPath); } if (browser.equals("chrome")) { driver = new ChromeDriver(); } else if (browser.equals("firefox")) { driver = new FirefoxDriver(); } else { throw new RuntimeException("Please create a driver for " + browser); } } @Test(dataProvider = "searchStrings") public void searchGoogle(final String searchKey) { System.out.println("Search " + searchKey + " in google"); driver.navigate().to("http://www.google.com"); WebElement element = driver.findElement(By.name("q")); System.out.println("Enter " + searchKey); element.sendKeys(searchKey); System.out.println("submit"); element.submit(); (new WebDriverWait(driver, 10)).until(new ExpectedCondition() { public Boolean apply(WebDriver d) { return d.getTitle().toLowerCase().startsWith(searchKey.toLowerCase()); } }); System.out.println("Got " + searchKey + " results"); } @DataProvider private Object[][] searchStrings() { return new Object[][] { { "TestNG" }, { "Selenium" } }; } @AfterTest public void quitDriver() throws Exception { driver.quit(); } }
testng.xml
will have two tests and both the tests will run the same test class. We want TestNgSeleniumChromeTest
to run on a chrome browser so we have set the browser
parameter to chrome
. Likewise, we want TestNgSeleniumFirefoxTest
to run on a firefox browser so the browser
is set to value firefox
.
testngBrowserConfigurable.xml:
<?xml version="1.0" encoding="UTF-8"?> <suite name="TestNgSeleniumSuite" parallel="false"> <test name="TestNgSeleniumChromeTest"> <parameter name="browser" value="chrome"></parameter> <parameter name="driverPath" value="c://selenium/chromedriver.exe"></parameter> <classes> <class name="com.javacodegeeks.testng.selenium.TestNGSeleniumBrowserCfgExample" /> </classes> </test> <test name="TestNgSeleniumFirefoxTest"> <parameter name="browser" value="firefox"></parameter> <classes> <class name="com.javacodegeeks.testng.selenium.TestNGSeleniumBrowserCfgExample" /> </classes> </test> </suite>
As you can see below, the test runs for both the browsers.
Output:
[TestNG] Running: C:\javacodegeeks_ws\testNGSelenium\src\test\resources\com\javacodegeeks\testng\spring\testngBrowserConfigurable.xml You are testing on browser chrome Starting ChromeDriver 2.14.313457 (3d645c400edf2e2c500566c9aa096063e707c9cf) on port 7342 Only local connections are allowed. Search TestNG in google Enter TestNG submit Got TestNG results Search Selenium in google Enter Selenium submit Got Selenium results You are testing on browser firefox Search TestNG in google Enter TestNG submit Got TestNG results Search Selenium in google Enter Selenium submit Got Selenium results =============================================== TestNgSeleniumSuite Total tests run: 4, Failures: 0, Skips: 0 ===============================================
6. TestNG Selenium dependency based tests
Suppose you want to run some tests only after a page is loaded, you can make sure this happens by making the tests depend on the method that is responsible for loading the page.
In the below example, we open http://examples.javacodegeeks.com/ and then search for TestNG articles. Once the page is loaded, we search for article called ‘TestNG Maven Project Example’ and click on it.
There are two aspects to this scenario, the first one deals with searching TestNG articles and the second one, which is about clicking an article from the search results comes into picture only after the search results are returned.
In the below class, test clickOnJCGTestNGArticle()
is about clicking on ‘TestNG Maven Project Example’ article whereas searchTestNGInJCG() is about searching TestNG in Java Code Geeks. Since clickOnJCGTestNGArticle()
depends on test searchTestNGInJCG()
, we modify @Test
annotation and set the dependsOnMethod
attribute to searchTestNGInJCG
.
TestNGSeleniumDependentMethodExample:
package com.javacodegeeks.testng.selenium; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @ContextConfiguration("driver_context.xml") public class TestNGSeleniumDependentMethodExample extends AbstractTestNGSpringContextTests { @Autowired private WebDriver driver; @BeforeClass public void printBrowserUsed() { System.out.println("Driver used is: " + driver); } @Test(dependsOnMethods="searchTestNGInJCG") public void clickOnJCGTestNGArticle() { System.out.println("You are in page " + driver.getTitle()); (new WebDriverWait(driver, 10)).until(new ExpectedCondition() { public Boolean apply(WebDriver d) { WebElement link = driver.findElement(By.linkText("TestNG Maven Project Example")); if (link != null) { System.out.println("Going to click on '" + link.getText() + "'"); link.click(); } return link != null; } }); assertPageTitle("TestNG Maven Project Example"); } @Test public void searchTestNGInJCG() { final String searchKey = "TestNG"; System.out.println("Search " + searchKey + " in JCG"); driver.navigate().to("http://examples.javacodegeeks.com/"); (new WebDriverWait(driver, 10)).until(new ExpectedCondition() { public Boolean apply(WebDriver d) { WebElement popup = d.findElement(By.linkText("Close this popup")); if (popup != null) { System.out.println("Found popup, close it"); popup.click(); } return popup != null; } }); WebElement element = driver.findElement(By.name("s")); System.out.println("Enter " + searchKey); element.sendKeys(searchKey); System.out.println("submit"); element.submit(); assertPageTitle("You searched for " + searchKey); System.out.println("Got " + searchKey + " results"); } private void assertPageTitle(final String title) { (new WebDriverWait(driver, 10)).until(new ExpectedCondition() { public Boolean apply(WebDriver d) { System.out.println("TITLE: " + d.getTitle()); return d.getTitle().toLowerCase() .startsWith(title.toLowerCase()); } }); } @AfterSuite public void quitDriver() throws Exception { driver.quit(); } }
testngDependencyTests.xml:
<?xml version="1.0" encoding="UTF-8"?> <suite name="TestNgSeleniumSuite" parallel="false"> <test name="TestNgSeleniumTest"> <classes> <class name="com.javacodegeeks.testng.selenium.TestNGSeleniumDependentMethodExample" /> </classes> </test> </suite>
From the below output, you can see ‘TestNG’ articles are searched first and then article ‘TestNG Maven Project Example’ is clicked upon.
Output:
[TestNG] Running: C:\javacodegeeks_ws\testNGSelenium\src\test\resources\com\javacodegeeks\testng\selenium\testngDependencyTests.xml Driver used is: FirefoxDriver: firefox on WINDOWS (07d0226b-8d03-4ec1-8a62-fb7ae09546be) Search TestNG in JCG Found popup, close it Enter TestNG submit TITLE: You searched for TestNG | Examples Java Code Geeks Got TestNG results You are in page You searched for TestNG | Examples Java Code Geeks Going to click on 'TestNG Maven Project Example' TITLE: TestNG Maven Project Example | Examples Java Code Geeks =============================================== TestNgSeleniumSuite Total tests run: 2, Failures: 0, Skips: 0 ===============================================
Download the Eclipse Project
In this article, I have shown you some examples of TestNG and Selenium integration.
You can download the full source code of this example here: testNGSelenium.zip
Worked well with Chrome but not Firefox. It looks not compatible with Firefox version 56.0(64-bit). Which version of Firefox should be used?
It works well if you have version 47.0.1 of Firefox