TestNG Tutorial

โšก Smart Summary

TestNG is a Next-Generation Java testing framework that pairs with Selenium for structured automation, rich reporting, and parallel execution. This tutorial covers the core annotations, project setup in Eclipse, writing the first test case, HTML reports, and advanced parameter usage.

  • ๐Ÿงฑ Core Framework: TestNG extends JUnit ideas with annotations, grouping, and parallel test execution for Selenium suites.
  • ๐Ÿท๏ธ Annotations Drive Flow: @Test, @BeforeMethod, @AfterMethod, @BeforeTest, and @AfterTest sequence setup, test, and teardown.
  • ๐Ÿ—‚๏ธ Eclipse Setup: Build a TestNG project, add the TestNG library and Selenium JARs, then generate test classes from the wizard.
  • ๐Ÿ“Š Reporting: TestNG produces text, graphical, and HTML reports in the test-output folder, including chronological views.
  • โš™๏ธ Parameters: Use priority, alwaysRun, and dataProvider to control execution order and feed data into tests.
  • ๐Ÿค– AI Boost: AI coding assistants accelerate TestNG class generation, locator updates, and dataProvider scaffolding.

TestNG Tutorial

What is TestNG?

TestNG is an automation testing framework where “NG” stands for “Next Generation”. TestNG is inspired by JUnit and uses Java annotations (@) to control test flow. It overcomes JUnit’s earlier limitations and is designed to make end-to-end testing easier.

With TestNG you can generate a proper report and immediately see how many tests passed, failed, or were skipped. You can also re-run only the failed cases.

For example:

  • Suppose you have five test cases, each in its own method, written without TestNG. Three pass; the fourth fails. After fixing the fourth, you want to re-run only that one, since the first three already passed. This is hard to do with plain main()-method code.
  • TestNG provides a testng-failed.xml file in the test-output folder. Running that XML re-executes only the failed cases.

Beyond that, you will learn the advantages of TestNG, how to write test methods with @Test annotations, and how to convert your classes into a test suite that runs from Eclipse or the command line.

Why Use TestNG with Selenium?

By default, Selenium tests do not produce nicely formatted results. With TestNG plugged in, the test runner emits a structured report you can share with the team.

Most Selenium users prefer TestNG over JUnit because of its broader feature set. The key features for Selenium are:

  • Reports that include the number of test cases run, passed, failed, and skipped.
  • Easy grouping of test cases via a testng.xml file, with execution priorities.
  • Repeat a test multiple times without loops using invocationCount.
  • Run multiple tests on multiple browsers โ€” cross-browser testing support.
  • Smooth integration with Maven, Jenkins, and other CI tooling.
  • Readable annotations โ€” for example, @BeforeMethod, @AfterMethod, @BeforeTest, @AfterTest.
  • Selenium WebDriver has no native reporting; TestNG fills that gap with a clean HTML report like the one below.

TestNG HTML report sample for Selenium tests

  • TestNG simplifies test code. You no longer need a static main method; annotations decide what runs and when.

Usual Java test class structure with main method

TestNG test class structure using annotations

  • Uncaught exceptions are handled gracefully by TestNG. They are reported as failed steps without terminating the entire run.

Advantages of TestNG over JUnit

TestNG offers three major advantages over JUnit:

  • Annotations are easier to understand and use.
  • Test cases can be grouped and prioritised with less effort.
  • Parallel test execution is supported out of the box.

What is an Annotation in TestNG?

Annotations in TestNG are lines of code placed above a method to control how it is executed. They always start with the @ symbol. A simple example is shown below.

Example TestNG annotation above a Java method

Annotations are covered in detail in the section “Annotations Used in TestNG” later in this tutorial, so the example above is just to set expectations. TestNG annotations are easier to code and read than the JUnit equivalents, and they are essential when running tests on Selenium Grid where parallel execution matters.

How to Write Test Cases in TestNG

Writing a TestNG test case takes three steps:

  1. Write your business logic and place TestNG annotations above each method.
  2. Add metadata such as class name, group name, and package name.
  3. Run the TestNG class from your IDE or the command line.

Create a Test Case Using TestNG Annotations

Now we will create our first test case using TestNG annotations in Selenium. Before writing the test, set up a new TestNG project in Eclipse and call it FirstTestNGProject.

Setting Up a New TestNG Project

Step 1) Click File > New > Java Project.

Eclipse menu to create a new Java project

Step 2) Enter FirstTestNGProject as the project name and click Next.

New Java project wizard with name FirstTestNGProject

Step 3) Import the TestNG libraries. Click the Libraries tab and then Add Libraryโ€ฆ.

Libraries tab with Add Library option in Eclipse

Step 4) In the Add Library dialog, choose TestNG and click Next.

Selecting TestNG in the Add Library dialog

Step 5) Click Finish.

Finishing the Add Library wizard

TestNG should now appear in the Libraries list.

TestNG visible in the Libraries list

Step 6) Add the JAR files that contain the Selenium API. These come from the Java client driver downloaded from selenium.dev/downloads.

Add External JARs dialog in Eclipse

Navigate to the folder where the Selenium JARs are stored.

Selecting Selenium JAR files for the build path

After adding the external JARs, the screen should look like this.

Selenium JARs added to the Libraries list

Step 7) Click Finish. The new FirstTestNGProject appears in the Package Explorer.

FirstTestNGProject visible in Package Explorer

How to Create a New TestNG Test File

With the project ready, create a new TestNG file.

Step 1) Right-click the src folder and choose New > Otherโ€ฆ.

New Other menu from the src folder in Eclipse

Step 2) Expand the TestNG folder, select TestNG class, and click Next.

TestNG class option in the New wizard

Step 3) Enter the values shown below and click Finish. The Java file is named FirstTestNGFile.

TestNG class wizard with FirstTestNGFile values

Step 4) Eclipse generates the TestNG template shown below.

Generated TestNG class template in Eclipse editor

Coding Your First TestNG Test Case

Create the first test case that verifies the title of the Mercury Tours homepage.

package firsttestngpackage;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.Test;

public class FirstTestNGFile {

    public String baseUrl = "https://demo.guru99.com/test/newtours/";
    public WebDriver driver;

    @Test
    public void verifyHomepageTitle() {
        System.out.println("launching firefox browser");
        // Selenium 4 ships Selenium Manager, so the driver path is no longer required.
        driver = new FirefoxDriver();
        driver.get(baseUrl);
        String expectedTitle = "Welcome: Mercury Tours";
        String actualTitle = driver.getTitle();
        Assert.assertEquals(actualTitle, expectedTitle);
        driver.quit();
    }
}

Things to notice:

  • TestNG does not need a main() method.
  • Methods do not need to be static.
  • The @Test annotation marks verifyHomepageTitle() as a test case.
  • Annotations live in the org.testng.annotations.* package.
  • The Assert class from org.testng.Assert drives verifications.

You may have multiple @Test annotations in a single TestNG file. We cover that in the “Annotations Used in TestNG” section.

Running the Test

Right-click the file and run it as a TestNG test. Eclipse produces two outputs โ€” a text result in the Console window and a graphical result in the TestNG Results window.

TestNG Results window with test outcome

Eclipse Console window with TestNG text output

Checking Reports Created by TestNG

The Console window provides a text-based summary while the TestNG Results window shows a graphical view.

Text vs graphical TestNG result comparison

Generating HTML Reports

TestNG can also generate full HTML reports.

Step 1) After running FirstTestNGFile, right-click the project and choose Refresh.

Refresh option for the TestNG project in Eclipse

Step 2) A test-output folder appears. Expand it and locate index.html โ€” the HTML report for the most recent run.

test-output folder with index.html highlighted

Step 3) Double-click index.html to open it inside Eclipse’s browser. Press F5 to refresh after future runs.

TestNG HTML index report rendered in Eclipse

Annotations Used in TestNG

You have already seen the @Test annotation. The rest of this section covers the most useful advanced annotations.

Multiple Test Cases

A single TestNG file can hold multiple @Test annotations. By default, methods annotated with @Test execute in alphabetical order. In the code below, methods c_test, a_test, and b_test run alphabetically regardless of source order.

Multiple @Test methods in a single TestNG class

Run the code and open index.html. Click Chronological view.

Chronological view of multiple TestNG methods

Parameters

To override default ordering, use the priority parameter. Parameters are keywords that modify an annotation’s behaviour.

  • Assign a value with =.
  • Wrap parameters in parentheses placed immediately after the annotation, as shown below.

TestNG annotation with parameter and value syntax

TestNG executes @Test annotations from the lowest priority value to the highest. The priority numbers do not need to be consecutive.

Full code with @Test priority parameters

The HTML report confirms that methods executed in ascending priority order.

TestNG report showing methods run by ascending priority

Multiple Parameters

Besides priority, @Test accepts the alwaysRun parameter (true or false). To use two or more parameters in a single annotation, separate them with a comma:

@Test(priority = 0, alwaysRun = true)

Example of multiple parameters inside a @Test annotation

@BeforeTest and @AfterTest

@BeforeTest Methods under this annotation run before the first test case in the TestNG file.
@AfterTest Methods under this annotation run after all test cases in the TestNG file finish.

Consider the code below.

package firsttestngpackage;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.*;

public class FirstTestNGFile {

    public String baseUrl = "https://demo.guru99.com/test/newtours/";
    public WebDriver driver;

    @BeforeTest
    public void launchBrowser() {
        System.out.println("launching firefox browser");
        driver = new FirefoxDriver();
        driver.get(baseUrl);
    }

    @Test
    public void verifyHomepageTitle() {
        String expectedTitle = "Welcome: Mercury Tours";
        String actualTitle = driver.getTitle();
        Assert.assertEquals(actualTitle, expectedTitle);
    }

    @AfterTest
    public void terminateBrowser() {
        driver.quit();
    }
}

From the table and code, we can predict that the sequence will be:

  • 1st โ€” launchBrowser()
  • 2nd โ€” verifyHomepageTitle()
  • 3rd โ€” terminateBrowser()

The placement of annotation blocks in the source file does not affect their execution order. Try reshuffling the methods as shown below.

package firsttestngpackage;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.*;

public class FirstTestNGFile {

    public String baseUrl = "https://demo.guru99.com/test/newtours/";
    public WebDriver driver;

    @AfterTest                              // Jumbled
    public void terminateBrowser() {
        driver.quit();
    }

    @BeforeTest                             // Jumbled
    public void launchBrowser() {
        System.out.println("launching firefox browser");
        driver = new FirefoxDriver();
        driver.get(baseUrl);
    }

    @Test                                   // Jumbled
    public void verifyHomepageTitle() {
        String expectedTitle = "Welcome: Mercury Tours";
        String actualTitle = driver.getTitle();
        Assert.assertEquals(actualTitle, expectedTitle);
    }
}

Run the code and verify the result.

TestNG result confirming order despite jumbled annotations

@BeforeMethod and @AfterMethod

@BeforeMethod Methods under this annotation run before each test method.
@AfterMethod Methods under this annotation run after each test method.

In Mercury Tours, suppose we want to verify the titles of two target pages reached from the homepage.

Three links from Mercury Tours homepage

The flow of the test is:

  • Open the homepage and verify its title.
  • Click REGISTER and verify the title of its target page.
  • Go back to the homepage and verify the title.
  • Click SUPPORT and verify the title of its target page.
  • Go back to the homepage and verify the title again.

The code below shows how @BeforeMethod and @AfterMethod handle the repeated steps.

package firsttestngpackage;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.*;

public class FirstTestNGFile {

    public String baseUrl = "https://demo.guru99.com/test/newtours/";
    public WebDriver driver;
    public String expected = null;
    public String actual = null;

    @BeforeTest
    public void launchBrowser() {
        System.out.println("launching firefox browser");
        driver = new FirefoxDriver();
        driver.get(baseUrl);
    }

    @BeforeMethod
    public void verifyHomepageTitle() {
        String expectedTitle = "Welcome: Mercury Tours";
        String actualTitle = driver.getTitle();
        Assert.assertEquals(actualTitle, expectedTitle);
    }

    @Test(priority = 0)
    public void register() {
        driver.findElement(By.linkText("REGISTER")).click();
        expected = "Register: Mercury Tours";
        actual = driver.getTitle();
        Assert.assertEquals(actual, expected);
    }

    @Test(priority = 1)
    public void support() {
        driver.findElement(By.linkText("SUPPORT")).click();
        expected = "Under Construction: Mercury Tours";
        actual = driver.getTitle();
        Assert.assertEquals(actual, expected);
    }

    @AfterMethod
    public void goBackToHomepage() {
        driver.findElement(By.linkText("Home")).click();
    }

    @AfterTest
    public void terminateBrowser() {
        driver.quit();
    }
}

After running the test, TestNG reports the sequence below.

TestNG report sequence using BeforeMethod and AfterMethod

In short: place setup steps inside @BeforeMethod and cleanup or navigation reset inside @AfterMethod so each test case starts and ends in a known state.

Summary of TestNG Annotations

  • @BeforeSuite: runs before all tests in the suite.
  • @AfterSuite: runs after all tests in the suite.
  • @BeforeTest: runs before any test method belonging to the classes inside a <test> tag.
  • @AfterTest: runs after all test methods belonging to the classes inside a <test> tag.
  • @BeforeGroups: runs shortly before the first test method that belongs to any listed group.
  • @AfterGroups: runs shortly after the last test method that belongs to any listed group.
  • @BeforeClass: runs before the first test method in the current class.
  • @AfterClass: runs after all test methods in the current class.
  • @BeforeMethod: runs before each test method.
  • @AfterMethod: runs after each test method.
  • @Test: marks the method as a test case.

FAQs

JUnit 5 modernised JUnit with the Jupiter API and extension model. TestNG still leads on parallel execution, suite-level grouping, dependsOn, and DataProvider. Many Selenium teams pick TestNG for end-to-end suites and JUnit 5 for unit tests.

Add parallel=”methods” or parallel=”classes” plus a thread-count attribute on the <suite> tag inside testng.xml. TestNG then distributes test methods across threads, ideal for Selenium Grid or cloud cross-browser runs.

@DataProvider feeds multiple data sets into a single @Test method. Each row in the provider is one execution. It is the standard pattern for data-driven Selenium tests against forms, search boxes, or login screens.

Yes. AI coding assistants generate TestNG skeletons, annotate @Test methods, build Page Object classes, and draft DataProvider arrays from sample CSVs, sharply reducing scaffolding time.

Generative AI ingests testng-results.xml and Surefire logs, clusters similar failures, suggests likely root causes, and drafts Jira tickets. This shortens flaky-test triage and helps QA leads prioritise CI fixes.

Summarize this post with: