TestNG Refresher for SDETs

Share with friends
โฑ๏ธ ๐‘น๐’†๐’‚๐’…๐’Š๐’๐’ˆ ๐‘ป๐’Š๐’Ž๐’†: 4 ๐˜ฎ๐˜ช๐˜ฏ๐˜ถ๐˜ต๐˜ฆ๐˜ด โšก๏ธ
Save Story for Later (0)
Please login to bookmark Close

Youโ€™re at the right place if youโ€™re looking forward to Refresh and Relearn TestNG in the fastest possible way.

Whether youโ€™re a seasoned SDET or new to test automation, this refresher will help you master TestNG. You will become a TestNG sorcerer. TestNG is more than a testing framework; itโ€™s our magical toolkit for crafting powerful, efficient, and elegant tests. Ready to go?

๐Ÿ“Œ Got a better free video course than the one above?ย Share the link in the commentsย for it to be considered to replace the video above!


Why TestNG is the Gandalf of Testing Frameworks?

TestNG (Test Next Generation) is a Java-based testing framework that puts you in control of your test execution. Its key strengths include:

  • Rich Annotations: Simplifies test case setup and teardown.
  • Data-Driven Testing: Handles test data like a pro.
  • Parallel Execution: Speeds up testing by running multiple tests simultaneously.
  • Seamless Integration: Works like a charm with Selenium, CI/CD tools, and reporting libraries.

Letโ€™s explore its magic with real-world examples and executable code. ๐Ÿš€


Mastering TestNG Annotations ๐ŸŽจ

TestNG annotations are the spells that make your test scripts manageable and powerful. Hereโ€™s a quick overview:

AnnotationPurposeExample
@TestMarks a method as a test method.@Test public void searchTest() {}
@BeforeSuiteRuns before all tests in the suite.@BeforeSuite public void initializeSuite() {}
@AfterSuiteRuns after all tests in the suite.@AfterSuite public void cleanupSuite() {}
@BeforeTestExecutes before <test> in the XML.@BeforeTest public void setupTests() {}
@AfterTestExecutes after <test> in the XML.@AfterTest public void cleanupTests() {}
@BeforeClassRuns before the first test in the current class.@BeforeClass public void setupClass() {}
@AfterClassRuns after all tests in the current class.@AfterClass public void cleanupClass() {}
@BeforeMethodRuns before each test method.@BeforeMethod public void setupMethod() {}
@AfterMethodRuns after each test method.@AfterMethod public void cleanupMethod() {}
@DataProviderSupplies test data for methods.@DataProvider(name = "data") public Object[][] testData() {}
@ParametersInjects parameters from the XML file.@Parameters({ "browser" }) public void setup(String browser) {}
@ListenersAdds listeners for custom reporting or actions during execution.@Listeners(CustomListener.class)
@FactoryDynamically creates instances of test classes.@Factory public Object[] createInstances() {}

A Practical Example ๐Ÿ•น๏ธ

Hereโ€™s a full example of a TestNG test suite that searches Google, clicks the fourth result, and closes the browser.

1. TestSetup.java

package tests;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.*;

public class TestSetup {
    protected WebDriver driver;

    @BeforeSuite
    public void beforeSuite() {
        System.out.println("Initializing Test Suite...");
    }

    @BeforeClass
    public void beforeClass() {
        System.out.println("Setting up before class...");
    }

    @Parameters("browser")
    @BeforeMethod
    public void setUp(@Optional("chrome") String browser) {
        System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
        driver = new ChromeDriver();
        driver.manage().window().maximize();
    }

    @AfterMethod
    public void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }

    @AfterClass
    public void afterClass() {
        System.out.println("Cleaning up after class...");
    }

    @AfterSuite
    public void afterSuite() {
        System.out.println("Test Suite Execution Complete.");
    }
}

2. GoogleSearchTest.java

package tests;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.util.List;

public class GoogleSearchTest extends TestSetup {

    @Test(dataProvider = "searchTerms")
    public void googleSearch(String searchTerm) {
        driver.get("https://www.google.com");
        driver.findElement(By.name("q")).sendKeys(searchTerm);
        driver.findElement(By.name("btnK")).click();

        List<WebElement> results = driver.findElements(By.cssSelector(".LC20lb"));
        Assert.assertTrue(results.size() >= 4, "Less than 4 results found!");

        results.get(3).click();
        System.out.println("Clicked the fourth result for: " + searchTerm);
    }

    @DataProvider(name = "searchTerms")
    public Object[][] searchData() {
        return new Object[][] {
            {"TestNG"},
            {"Selenium"},
            {"Java Programming"}
        };
    }
}

3. testng.xml

<suite name="GoogleSearchSuite">
    <test name="GoogleSearchTests">
        <parameter name="browser" value="chrome"/>
        <classes>
            <class name="tests.GoogleSearchTest"/>
        </classes>
    </test>
</suite>

Advanced Features in TestNG ๐Ÿ”ฌ

1. Parallel Test Execution

Boost execution speed with parallel tests.

<suite name="ParallelSuite" parallel="methods" thread-count="3">
    <test name="ParallelTest">
        <classes>
            <class name="tests.GoogleSearchTest"/>
        </classes>
    </test>
</suite>

2. Retry Logic for Flaky Tests

package utils;

import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;

public class RetryAnalyzer implements IRetryAnalyzer {
    private int retryCount = 0;
    private static final int maxRetryCount = 2;

    @Override
    public boolean retry(ITestResult result) {
        if (retryCount < maxRetryCount) {
            retryCount++;
            return true;
        }
        return false;
    }
}
@Test(retryAnalyzer = utils.RetryAnalyzer.class)
public void flakyTest() {
    Assert.fail("Simulating a flaky test.");
}

3. Test Grouping

@Test(groups = {"smoke"})
public void smokeTest() {
    System.out.println("Running smoke test...");
}

@Test(groups = {"regression"})
public void regressionTest() {
    System.out.println("Running regression test...");
}

Another example, that incorporates all the TestNG annotations in a cohesive, practical scenario. This example demonstrates a test script for interacting with a search engine (Google). It performs various checks, such as parameterized and data-driven testing. It also includes listeners and grouping.


Project Directory Structure

Example/
โ”œโ”€โ”€ src/main/java/
โ”œโ”€โ”€ src/test/java/
โ”‚ โ”œโ”€โ”€ config/
โ”‚ โ”‚ โ””โ”€โ”€ TestSetup.java
โ”‚ โ”œโ”€โ”€ listeners/
โ”‚ โ”‚ โ””โ”€โ”€ CustomListener.java
โ”‚ โ”œโ”€โ”€ tests/
โ”‚ โ”‚ โ””โ”€โ”€ GoogleSearchTest.java
โ”‚ โ”œโ”€โ”€ testng.xml

TestSetup.java (Reusable Configuration)

package config;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.*;

public class TestSetup {
protected WebDriver driver;

@BeforeSuite
public void beforeSuite() {
System.out.println("๐Ÿ”ง Initializing suite-wide setup...");
}

@AfterSuite
public void afterSuite() {
System.out.println("๐Ÿ”ง Cleaning up after suite...");
}

@BeforeTest
public void beforeTest() {
System.out.println("๐Ÿ”ง Setting up before test...");
}

@AfterTest
public void afterTest() {
System.out.println("๐Ÿ”ง Tearing down after test...");
}

@BeforeClass
public void beforeClass() {
System.out.println("๐Ÿ”ง Setting up before the class...");
}

@AfterClass
public void afterClass() {
System.out.println("๐Ÿ”ง Cleaning up after the class...");
}

@BeforeMethod
@Parameters("browser")
public void setUp(@Optional("chrome") String browser) {
System.out.println("๐Ÿ”ง Launching browser: " + browser);
driver = new ChromeDriver();
driver.manage().window().maximize();
}

@AfterMethod
public void tearDown() {
System.out.println("๐Ÿ”ง Closing browser...");
if (driver != null) {
driver.quit();
}
}
}

GoogleSearchTest.java (Test Implementation)

package tests;

import config.TestSetup;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.testng.Assert;
import org.testng.annotations.*;

public class GoogleSearchTest extends TestSetup {

@DataProvider(name = "searchTerms")
public Object[][] provideSearchTerms() {
return new Object[][] {
{"Selenium WebDriver"},
{"TestNG Annotations"},
{"Java Tutorial"}
};
}

@Test(groups = {"smoke", "search"}, priority = 1)
public void openGoogle() {
driver.get("https://www.google.com");
String title = driver.getTitle();
System.out.println("Page title: " + title);
Assert.assertTrue(title.contains("Google"), "Google page did not load!");
}

@Test(dataProvider = "searchTerms", groups = {"functional", "search"}, priority = 2)
public void performSearch(String searchTerm) {
driver.get("https://www.google.com");
driver.findElement(By.name("q")).sendKeys(searchTerm + Keys.ENTER);
System.out.println("Searched for: " + searchTerm);
Assert.assertTrue(driver.getTitle().contains(searchTerm), "Search results not loaded!");
}

@Test(dependsOnMethods = {"performSearch"}, groups = {"functional", "search"}, priority = 3)
public void clickFourthResult() {
driver.findElement(By.cssSelector("h3")).click();
System.out.println("Clicked on the fourth result.");
}

@Test(threadPoolSize = 2, invocationCount = 2, groups = {"performance"}, priority = 4)
public void loadPerformanceTest() {
driver.get("https://www.google.com");
System.out.println("Loaded Google for performance test!");
}
}

CustomListener.java (Listener Example)

package listeners;

import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

public class CustomListener implements ITestListener {

@Override
public void onTestStart(ITestResult result) {
System.out.println("๐Ÿ” Starting test: " + result.getName());
}

@Override
public void onTestSuccess(ITestResult result) {
System.out.println("โœ… Test passed: " + result.getName());
}

@Override
public void onTestFailure(ITestResult result) {
System.out.println("โŒ Test failed: " + result.getName());
}

@Override
public void onTestSkipped(ITestResult result) {
System.out.println("โš  Test skipped: " + result.getName());
}

@Override
public void onStart(ITestContext context) {
System.out.println("๐Ÿš€ Starting suite: " + context.getName());
}

@Override
public void onFinish(ITestContext context) {
System.out.println("๐Ÿ Finished suite: " + context.getName());
}
}

testng.xml (Execution Configuration)

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="TestNG Suite" parallel="tests" thread-count="2">
<listeners>
<listener class-name="listeners.CustomListener"/>
</listeners>
<test name="Google Search Tests">
<parameter name="browser" value="chrome"/>
<classes>
<class name="tests.GoogleSearchTest"/>
</classes>
</test>
</suite>

Features Covered

  1. Annotations:
    • Setup/Teardown: @BeforeSuite, @AfterSuite, etc.
    • Test Execution: @Test, @DataProvider, @Parameters.
  2. Grouping: @Test(groups = {"smoke", "functional"}).
  3. Dependency Testing: @Test(dependsOnMethods = ...).
  4. Parallel Execution: parallel="tests" in testng.xml.
  5. Listeners: Implemented a custom listener to handle events.
  6. Threading: Used threadPoolSize and invocationCount.

Next Steps

Add this project to your GitHub repo. Let me know if you’d like further enhancements. These may include reporting with ExtentReports or Allure.

FAQs

1. What makes TestNG better than JUnit?

  • Flexible annotations, better dependency handling, and native support for parallel execution.

2. Can I integrate TestNG with Selenium?

  • Absolutely! TestNG and Selenium are a match made in testing heaven.

3. What is the use of @DataProvider?

  • Itโ€™s used to supply test data, enabling parameterized testing.

Article Contributors

  • Captain Jarhead
    (Author)
    Chief Java Officer, QABash

    Captain Jarhead is a fearless Java expert with a mission to conquer bugs, optimize code, and brew the perfect Java app. Armed with a JVM and an endless supply of caffeine, Captain Jarhead navigates the wild seas of code, taming exceptions and turning null pointers into smooth sailing. A true master of beans, loops, and classes, Captain Jarhead ensures no bug escapes his radar!

  • Ishan Dev Shukl
    (Reviewer)
    SDET Manager, Nykaa

    With 13+ years in SDET leadership, I drive quality and innovation through Test Strategies and Automation. I lead Testing Center of Excellence, ensuring high-quality products across Frontend, Backend, and App Testing. "Quality is in the details" defines my approachโ€”creating seamless, impactful user experiences. I embrace challenges, learn from failure, and take risks to drive success.

Subscribe to QABash Weekly ๐Ÿ’ฅ

Dominate โ€“ Stay Ahead of 99% Testers!

Leave a Reply

Scroll to Top
×