Next-Gen App & Browser
Testing Cloud

Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

Next-Gen App & Browser Testing Cloud

TestNG Framework Tutorial: A Comprehensive Guide, with Examples & Best Practices

Learn TestNG, a flexible Java testing framework, with features, setup, examples, and best practices for scalable, data-driven, and parallel test automation.

Published on: September 10, 2025

  • Share:

The TestNG framework has become a go-to choice for developers and testers who need more than just basic test execution.

Built to handle everything from simple unit checks to large-scale automation, TestNG brings flexibility, powerful configuration options, and seamless integration with modern tools, making it an essential part of any robust testing strategy.

Overview

TestNG streamlines test automation with flexible annotations and configuration. It also supports parallel execution and data-driven testing for faster results.

Steps to Set Up TestNG Framework

  • Install Java Development Kit (JDK).
  • Set up an IDE like Eclipse or IntelliJ IDEA.
  • Install TestNG via Eclipse Marketplace or add a Maven/Gradle dependency.
  • Create a new TestNG project and write test classes using annotations like @Test.
  • Configure testng.xml to define test suites, execution order, and groups.

How to Run Parallel Tests in TestNG?

  • Set up JDK, IDE, and add TestNG via Maven/Gradle or Eclipse Marketplace.
  • Create a TestNG test class and configure LambdaTest Selenium Grid capabilities
  • Define parallel tests in testng.xml and run with mvn test -Dsuite=parallel.xml.
  • Check execution logs and videos on the LambdaTest Dashboard.

Advanced Use Cases of TestNG Framework

  • Group test cases: Allows you to manage dependencies for selective execution of complex suites.
  • Prioritize tests: Enables control over execution order and temporary enabling/disabling of tests.
  • Assertions: Validates outcomes with clear feedback and custom messages.
  • Data-driven tests: Run a single test multiple times with different input sets using @DataProvider.
  • Parameterization: Pass different values via XML or annotations to enhance test flexibility.
  • Listeners: Trigger custom actions like logging, reporting, or notifications during test execution.
  • Annotations: Manage test flow using @BeforeTest, @AfterTest, and @Test.
  • TestNG reports: Generate detailed reports via Reporter Log or integrate with Jenkins.

What Is TestNG?

TestNG is a testing framework that is designed to simplify the process of writing, managing, and executing tests. It supports a wide range of testing types, including unit, functional, integration, and end-to-end tests.

Unlike other frameworks like JUnit, TestNG offers more flexibility, scalability, and advanced features such as:

  • Test grouping: Organize related test cases into logical groups for easier execution.
  • Parallel execution: Run multiple tests simultaneously to reduce execution time.
  • Test execution priorities: Define the order in which tests should run.
  • Annotation-based configuration: Use annotations like @Test, @BeforeSuite, and @AfterClass to manage test flow.
  • Parameterized testing: Pass dynamic values to test methods using @Parameters.
  • Data-driven testing: Supply multiple data sets with @DataProvider.
  • Dependency control: Ensure tests run only after specified dependencies have passed.
  • Customizable test suites: Configure and manage tests through an XML file (testng.xml).
  • Detailed reporting: Automatically generate HTML and XML reports after execution.
  • Seamless integration: Works with Selenium, Maven, Gradle, and CI/CD tools like Jenkins.

By combining these capabilities, TestNG is widely used in Selenium automation for creating structured, maintainable, and high-performance automated test suites.

Key Features of TestNG

The TestNG framework is designed to handle complex test scenarios with advanced customization and seamless integration options. Some of its key features include:

  • Suite-level execution control: Ability to configure multiple test suites and execute them sequentially or selectively.
  • Dynamic test generation: Create test cases at runtime without hardcoding them in advance.
  • Listeners and reporting APIs: Extend reporting and logging by implementing custom listeners such as ITestListener or ISuiteListener.
  • Parallel data providers: Execute data-driven tests where each data set can run in parallel threads.
  • Factory methods: Generate instances of test classes dynamically for parameterized class-level testing.
  • Flexible test inclusion/exclusion: Include or exclude tests at method, class, or package level using XML or annotations.
  • Built-in retry mechanism: Re-run failed tests automatically without restarting the entire suite.
  • Multiple assertions handling: Continue executing steps even after an assertion fails using soft assertions.
  • Test configuration inheritance: Share setup and teardown logic across multiple test classes through inheritance.
Note

Note: Run your TestNG tests efficiently at scale across 3,000+ browser and OS combinations. Try LambdaTest now!

Core Architecture of TestNG

The core architecture of the TestNG framework is designed to coordinate the test execution flow from configuration to reporting. It ensures that different modules, such as execution managers, data processors, and dependency handlers, work together in a unified process for efficient and organized testing.

  • Annotations Engine: Parses and executes test methods based on annotations.
  • Test Suite Executor: Reads configuration from testng.xml or programmatic input and coordinates test execution order.
  • Data Provider Processor: Supplies test methods with data sets for parameterized execution.
  • Dependency Resolver: Manages execution flow when tests have dependencies on others.
  • Parallel Execution Manager: Allocates threads for running tests concurrently across methods, classes, or suites.
  • Listeners & Reporter Module: Captures execution events and generates detailed HTML/XML/JSON reports.
  • Integration Layer: Connects with build tools (Maven, Gradle), CI/CD platforms (Jenkins, GitLab CI), and test automation tools (Selenium, Appium).
  • Custom Extension Support: Allows developers to plug in custom logic at different execution stages.

Setting Up TestNG Framework in Your Environment

Before you start using the TestNG framework, make sure you have Java installed and a suitable IDE like Eclipse or IntelliJ IDEA set up. In this TestNG tutorial, you’ll learn how to add TestNG to your project and run your first test.

The installation process consists of the following steps.

  • Install JDK: You can download the Java Development Kit (JDK) from any of these sources:
  • Install Eclipse IDE: You can download and install a popular Java IDE, such as:
  • Install TestNG:
    • In Eclipse: Go to Help → Eclipse Marketplace → Search for TestNG → Install.

    • Restart IDE After Installing TestNG Plugin: If you install TestNG via Eclipse Marketplace, a restart of Eclipse is usually required.

    • Using Maven: Add the TestNG dependency in your pom.xml:
      <dependency>
          <groupId>org.testng</groupId>
          <artifactId>testng</artifactId>
          <version>7.10.2</version>
          <scope>test</scope>
      </dependency>
      

    • Using Gradle:Add the dependency in your build.gradle:
    • testImplementation 'org.testng:testng:7.10.2'

  • Create a TestNG Project: Set up your project structure and start writing test classes using TestNG annotations like @Test, @BeforeSuite, and @AfterClass.

  • Configure testng.xml: Use this file to define test suites, set execution order, and manage test groupings.

Writing Your First TestNG Script

Once you’ve set up the TestNG framework in your environment, you can write your first script to understand how it works in practice. In this TestNG tutorial will guide you through a simple automation scenario using Selenium WebDriver and assertions.

Test scenario:


For this demonstration the above test scenarios, you’ll use IntelliJ IDEA and create a Maven project. To add the TestNG framework dependencies, you need to update the pom.xml file as shown below:



<dependencies>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.15.0</version>
    </dependency>
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.10.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.github.bonigarcia</groupId>
        <artifactId>webdrivermanager</artifactId>
        <version>5.5.3</version>
    </dependency>
</dependencies>

Code Implementation:

Below is the code Implementation for the above test scenario:



package demoTestNG;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;


public class FirstTestNGScript {
    public static WebDriver driver = null;

    @BeforeTest
    public void setUp() {
        WebDriverManager.chromedriver().setup();
        driver = new ChromeDriver();
        driver.manage().window().maximize();
    }

    @Test
    public void firstTestCase() {
        System.out.println("Launching LambdaTest Registration Page...");
        driver.get("https://accounts.lambdatest.com/register");


        // Click on the "Sign In" link
        WebElement signInLink = driver.findElement(By.xpath("//a[text()='Sign In']"));
        signInLink.click();
        System.out.println("Clicked on the Sign In link.");


        // Assertion to verify page title
        String expectedTitle = "Sign in - LambdaTest";
        String actualTitle = driver.getTitle();
        Assert.assertEquals(actualTitle, expectedTitle, "Page title does not match!");
    }

    @AfterTest
    public void tearDown() {
        driver.quit();
        System.out.println("Browser closed successfully.");
    }
}


Test Execution

To run the above test case using Selenium Java with TestNG locally, you can configure and use the following testng.xml file:



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="FirstTestNGSuite">
    <test name="SignInNavigationTest">
        <classes>
            <class name="demoTestNG.FirstTestNGScript" />
        </classes>
    </test>
</suite>



testng-lt-outout

Code Walkthrough

Here is the code walkthrough of the executed test using TestNG with Selenium and Java on a local grid.

  • @BeforeTest : Executes setup steps before any test method.
  • WebDriverManager.chromedriver().setup() : Sets up the ChromeDriver automatically, avoiding manual driver configuration.
  • driver = new ChromeDriver() : Launches a new Chrome browser instance.
  • driver.manage().window().maximize() : Maximizes the browser window.
  • @Test : Marks the method as a test case.
  • driver.get("https://accounts.lambdatest.com/register") : Opens the specified URL in the browser.
  • driver.findElement(By.xpath("//a[text()='Sign In']")).click() : Clicks the "Sign In" link on the page.
  • Assert.assertEquals(actualTitle, expectedTitle, "Page title does not match!") : Validates that the actual page title matches the expected title, failing the test if they don’t match.
  • @AfterTest : Executes cleanup steps after all test methods.
  • driver.quit() : Closes all browser windows and ends the WebDriver session.

Achieving reliable test execution in TestNG-based Selenium automation can be challenging due to improper test configurations, dependency mismanagement, and parallel execution conflicts.

TestNG’s structured test management helps, but issues like flaky tests from timing mismatches or environment differences can still occur.


Leveraging cloud-based testing platforms can further enhance TestNG execution by offering consistent test environments, scalable infrastructure, and advanced debugging tools.


These platforms also simplify parallel execution, help reduce flakiness, and maintain reliability across diverse browser and OS combinations. One such platform is LambdaTest.

How to Run Parallel Tests in TestNG?

LambdaTest is a GenAI-native test execution platform that supports both manual testing and Selenium automation testing with TestNG across 3000+ browser and OS combinations.


...

It enables seamless parallel execution in TestNG, helping you scale tests efficiently, reduce execution time, and maintain reliability, all with a simple setup and minimal configuration.


In this TestNG framework example, we’ll run the same “Sign In” scenario in parallel on Firefox (Windows 8), Chrome (Windows 10), and Safari (macOS High Sierra). You only need to make a few changes to your testng.xml file.



<suite name="ParallelTests" parallel="tests" thread-count="3">
    <test name="WIN8TEST">
        <parameter name="browser" value="firefox"/>
        <parameter name="version" value="120.0"/>
        <parameter name="platform" value="WIN8"/>
        <classes>
            <class name="FirstTestScriptUsingWebDriver"/>
        </classes>
    </test>
    <test name="WIN10TEST">
        <parameter name="browser" value="chrome"/>
        <parameter name="version" value="121.0"/>
        <parameter name="platform" value="WIN10"/>
        <classes>
            <class name="FirstTestScriptUsingWebDriver"/>
        </classes>
    </test>


    <test name="MACTEST">
        <parameter name="browser" value="safari"/>
        <parameter name="version" value="11.0"/>
        <parameter name="platform" value="macos 10.13"/>
        <classes>
            <class name="FirstTestScriptUsingWebDriver"/>
        </classes>
    </test>
</suite>



Updating Your Script for Cloud Execution

In your test script, set up the connection to the LambdaTest Selenium Grid:


String gridURL = "https://hub.lambdatest.com/wd/hub";

Then configure your desired capabilities using the parameters from the testng.xml file:



ChromeOptions browserOptions = new ChromeOptions();
browserOptions.setPlatformName("Windows 10");
browserOptions.setBrowserVersion("dev");
HashMap<String, Object> ltOptions = new HashMap<String, Object>();
ltOptions.put("username", System.getenv("LT_USERNAME"));
ltOptions.put("accessKey", System.getenv("LT_ACCESS_KEY"));
ltOptions.put("video", true);
ltOptions.put("build", "TestNG");
ltOptions.put("project", "TestNG Parallel Run");
ltOptions.put("name", "TestNG Sample Test");
ltOptions.put("w3c", true);
ltOptions.put("plugin", "java-testNG");
browserOptions.setCapability("LT:Options", ltOptions);

You can use the LambdaTest Capabilities Generator to create this block automatically.

Text Execute:

Run the following command given below:

mvn test -Dsuite=parallel.xml

You can then view real-time execution logs and video recordings on the LambdaTest Automation Dashboard. Running parallel tests with TestNG in Selenium ensures faster feedback while covering different browsers and OS combinations in one go.

testng-lt-outout

To get started with TestNG, refer to the support documentation on executing Selenium tests with TestNG.

TestNG vs JUnit

TestNG and JUnit are both popular Java testing frameworks that help you handle complex test suites. However, each framework offers slightly different features and approaches, so choosing the right one depends on your specific testing needs.


AspectTestNGJUnit
Test ConfigurationOffers flexible and powerful XML-based configuration, supporting groups, dependencies, and parallel execution.Uses annotations with limited configuration options and no native support for grouping or dependencies.
Test GroupingSupports grouping of test methods, allowing selective test execution based on groups.Does not natively support test grouping; requires workarounds or extensions.
Dependency ManagementAllows tests to depend on other tests or groups, controlling execution order explicitly.Limited support for test dependencies; execution order is generally unpredictable.
Data-Driven TestingBuilt-in @DataProvider annotation for running tests with multiple data sets.Supports parameterized tests but requires additional setup and lacks native data providers.
Parallel ExecutionNatively supports parallel test execution through XML configuration.Parallelism was introduced in newer versions, but less mature and flexible than TestNG.
AnnotationsProvides a rich set of annotations like @BeforeSuite, @AfterGroups, and more, offering fine-grained control.Offers fewer annotations, mainly focused on basic lifecycle methods.
Exception TestingSupports specifying expected exceptions in @Test with flexibility.Allows expected exceptions, but is less flexible in configuration.
Integration with Build ToolsSeamlessly integrates with Maven, Gradle, and Jenkins with plugins for reporting and execution control.Also integrates well, but may require additional plugins for advanced features.
Community and PopularityWidely used for complex enterprise testing scenarios needing advanced features.Extremely popular, especially for unit testing, with broad community support.
Report GenerationOffers built-in detailed reports and supports custom listeners for enhanced reporting.Provides basic reporting; advanced reporting often requires third-party tools.

Common Pitfalls in TestNG and How to Avoid Them

The TestNG framework can cause unexpected test failures, skipped tests, or maintenance challenges. Understanding these issues and applying best practices helps you write more reliable and manageable test suites.

  • Problem: Tests silently skip without clear reasons, making debugging difficult.

  • Solution: Ensure proper usage of conditional annotations and always check for skipped tests in reports. Use listeners or Reporter Logs to capture why a test was skipped, and avoid disabling tests without clear documentation.


  • Problem: DataProviders cause tests to fail unpredictably due to incorrect data formats or mismatched parameters.

  • Solution: Double-check that the @DataProvider method returns the correct data structure matching the test method’s parameters. Validate data types and sizes before test execution and add meaningful error messages to catch mismatches early.


  • Problem: TestNG configuration XML files become complex and hard to maintain as the project grows.

  • Solution: Modularize your XML configurations by splitting tests into smaller suites and using the include and exclude tags. Maintain naming conventions and document suites clearly to improve readability and scalability.


  • Problem: Test results lack clarity due to minimal or inconsistent logging and reporting.

  • Solution: Utilize TestNG’s Reporter Log and implement custom listeners to capture detailed execution info. Standardize logging practices across tests to make debugging and analysis easier.


  • Problem: Tests fail intermittently (“flaky tests”) caused by shared state or improper setup/teardown.

  • Solution: Use @BeforeMethod and @AfterMethod to reset state before each test. Avoid static variables for test data, and ensure tests do not rely on external factors unless explicitly handled.


  • Problem: Incorrect or missing annotation usage leads to tests not being executed as expected.

  • Solution: Familiarize yourself with TestNG annotations and their execution order. Validate your test classes and methods have the correct annotations (@Test, @BeforeTest, etc.) and avoid mixing JUnit annotations accidentally.


  • Problem: Parameterization conflicts when parameters are not passed correctly, causing runtime errors.

  • Solution: Verify parameter names in the XML match those in the test methods. Use @Parameters annotation properly and confirm that optional parameters have default values or are handled to avoid null errors.


  • Problem: Overusing dependsOnMethods creates complex dependencies that make tests brittle and hard to maintain.

  • Solution: Minimize dependencies by designing independent tests. When dependencies are necessary, keep them simple and document the rationale clearly.


  • Problem: Ignoring exceptions in tests due to improper handling, resulting in false positives.

  • Solution: Always assert expected exceptions using expectedExceptions in @Test. Do not catch exceptions silently in test methods; instead, allow TestNG to detect failures accurately.


...

Advanced Use Cases of TestNG Framework

Apart from executing basic automated tests, the TestNG framework offers a variety of advanced features that go beyond simple validations.

These capabilities allow testers to create more organized, scalable, and maintainable test suites for complex projects.

  • Grouping Test Cases in TestNG: Lets you group test cases in TestNG that share common traits, enabling selective execution or exclusion of tests based on these groups. You can also define dependencies between groups to control the order tests are run, which helps manage complex suites efficiently.

  • Prioritizing Tests in TestNG: You can manage test execution by prioritizing tests in TestNG using the priority attribute within the @Test annotation. Tests with lower priority values run first, allowing you to control the execution order. You can also temporarily disable tests by setting the enabled attribute.

  • Assertions in TestNG: Using assertions in TestNG allows you to validate expected outcomes, such as checking equality, truth, or null values. When an assertion fails, the test fails, providing clear feedback on the issue. You can also add custom messages for better clarity, making assertions a key part of test validation.

  • DataProviders in TestNG: With the @DataProvider annotation, TestNG allows you to run a single test method multiple times using different data sets. This enables data-driven testing, reducing duplicate code while increasing coverage across diverse inputs. DataProviders in TestNG are a powerful way to manage test data efficiently.

  • Parameterization in TestNG: Supports parameterization, which allows you to pass different input values to tests via XML configuration files or annotations. Parameterization in TestNG enhances test flexibility and maintainability, making it easier to run the same test logic under varied conditions.

  • Listeners in TestNG: Provides hooks into the test execution lifecycle to trigger custom actions like logging, report generation, or notifications, all by just using the @listeners annotation. Using listeners in TestNG enhances your test framework's capabilities.

  • Annotations in TestNG: TestNG offers various annotations such as @BeforeTest, @AfterTest, and @Test to control the execution flow and lifecycle of tests. These annotations in TestNG help structure your tests, handle setup and teardown, and manage dependencies.

  • TestNG Reporter Log in Selenium: The built-in Reporter Log in TestNG generates detailed test execution reports, including timing, pass/fail status, and error details. This helps analyze test results without external tools.

  • Generate TestNG Reports in Jenkins: You can generate reports in TestNG by integrating them into Jenkins CI/CD pipelines using the TestNG plugin, which automatically generates and displays detailed test results after builds.

Best Practices for TestNG

Following best practices in TestNG ensures your tests are reliable, maintainable, and easy to manage.

  • Write Independent Tests: Design each test method to be self-contained without relying on the execution order or the outcome of other tests. This improves reliability and makes debugging easier.

  • Use Logical Grouping and Priorities: Organize tests into meaningful groups and assign priorities thoughtfully to control execution flow and focus on critical test scenarios.

  • Leverage Annotations Effectively: Use TestNG annotations like @BeforeMethod, @AfterMethod, @BeforeClass, and @AfterClass to manage setup and teardown tasks cleanly and avoid code duplication.

  • Implement Data-Driven Testing: Utilize @DataProvider to run tests with multiple data sets, enhancing coverage without duplicating test code.

  • Keep Test Data Separate: Store test data externally or in dedicated methods, avoiding hardcoded values in your test logic for easier maintenance and updates.

  • Maintain Clear XML Configurations: Organize TestNG XML files into manageable suites, using include and exclude tags, and document your test suite structure clearly.

  • Enhance Reporting and Logging: Use TestNG’s Reporter Log and custom listeners to capture detailed execution information, improving test result analysis and troubleshooting.

  • Refactor Regularly: Continuously review and update your test code to keep it clean, efficient, and aligned with evolving application requirements.

Conclusion

TestNG stands out as a versatile and powerful testing framework, providing robust features to create well-structured and maintainable automated test suites. Its support for parallel execution, flexible configuration, and advanced annotations enables testers to design scalable and efficient tests that adapt to complex scenarios.

By avoiding common pitfalls and adhering to best practices such as writing independent tests, using logical groupings, and leveraging data-driven techniques, you can maximize test reliability and clarity. Integrating TestNG with cloud platforms like LambdaTest further enhances execution consistency and accelerates feedback cycles.

Embracing these strategies will help you fully harness TestNG’s capabilities, delivering high-quality, resilient automation tailored to your project’s evolving needs.

Frequently Asked Questions(FAQs)

What advantages does TestNG offer for test parallelization compared to traditional frameworks?
TestNG simplifies parallel test execution with built-in support in its XML configuration, allowing tests to run across multiple threads or machines simultaneously. This reduces overall test runtime significantly. It also integrates easily with cloud grids for scalable, cross-browser parallel runs.
How can TestNG improve test maintenance in large projects?
TestNG supports modular test suite design through XML files and grouping features, making it easy to organize and selectively run tests. Its annotation-driven approach reduces boilerplate code and centralizes setup/teardown logic, resulting in cleaner and more maintainable tests.
Why is dependency management important in TestNG, and how is it typically handled?
Dependency management prevents tests from running prematurely when prerequisites fail, ensuring accurate results. TestNG handles this via dependsOnMethods and dependsOnGroups, allowing explicit control over test execution order and improving suite robustness.
What role do listeners play in enhancing TestNG’s functionality?
Listeners allow custom actions during test execution like logging, reporting, or notifications. By implementing interfaces such as ITestListener, developers can hook into test lifecycle events, providing enhanced visibility and control without cluttering test logic.
How does TestNG facilitate data-driven testing beyond simple parameterization?
TestNG’s @DataProvider annotation allows feeding multiple data sets to a single test method, enabling comprehensive test coverage with minimal code duplication. It supports dynamic data generation and parallel execution of data-driven tests for efficiency.
What strategies can be used to handle flaky tests when using TestNG?
To reduce flaky tests, avoid shared mutable state by isolating tests, use proper setup/teardown annotations, and leverage TestNG’s retry analyzer to rerun failed tests automatically. Also, externalize configuration to ensure consistent environments.
How can TestNG integrate with continuous integration pipelines effectively?
TestNG generates detailed XML and HTML reports which CI tools like Jenkins can consume. Plugins automate test runs on code commits, provide pass/fail analytics, and enable alerting mechanisms, promoting rapid feedback in the development lifecycle.
In what ways does TestNG’s annotation system simplify test lifecycle management?
Annotations like @BeforeSuite, @AfterTest, and @BeforeClass let you define setup and cleanup tasks at varying granularities. This modular approach avoids redundant code and clearly separates configuration from test logic for easier maintenance.
How can TestNG tests be scaled for cross-platform and cross-browser testing?
By parameterizing browser and platform details in XML configurations and combining with cloud Selenium grids, TestNG allows seamless scaling. This supports running identical test scenarios across diverse environments without changing test code.
What is the benefit of using soft assertions in TestNG tests?
Soft assertions let tests continue executing even if some assertions fail, collecting all failures before reporting. This provides a more comprehensive view of issues in a single test run and helps identify multiple defects at once.

Did you find this page helpful?

Helpful

NotHelpful

More Related Hubs

ShadowLT Logo

Start your journey with LambdaTest

Get 100 minutes of automation test minutes FREE!!

Signup for free