A Guide to TestNG: Building Robust Testing Frameworks

Table of contents
- What is TestNG?
- Installing and Configuring TestNG in Eclipse
- Creating a TestNG Project
- Understanding TestNG XML Files
- Controlling Test Execution
- TestNG Annotations
- Parameterization in TestNG
- TestNG Listeners
- Running Tests in Parallel
- TestNG Reporting
- Real-World Applications
- Best Practices for TestNG Frameworks
- Common Questions
- Conclusion

Welcome to this comprehensive guide on TestNG, a powerful testing framework widely used in Java-based automation projects. Whether you're new to automation testing or looking to enhance your framework-building skills, this guide will walk you through TestNG’s core features, setup, and practical applications. By the end, you’ll have a clear understanding of how TestNG can help you control test execution, manage test cases, and build robust automation frameworks.
What is TestNG?
TestNG(Test Next Generation) is a testing framework designed to simplify and enhance the process of writing and executing test cases, particularly for Java-based automation projects like Selenium, Appium, and REST API testing. It provides greater control over test case execution compared to plain Java, offering features like annotations, parameterization, parallel execution, and detailed reporting. TestNG is a cornerstone for building automation frameworks because it allows you to organize, prioritize, and execute test cases efficiently.
Why Use TestNG?
Control Over Test Execution: You can define dependencies, group test cases, and control the order of execution.
Flexibility: Run specific test cases (e.g., smoke tests) or skip others with a single click.
Data-Driven Testing: Test cases can be run with multiple sets of data using parameterization.
Parallel Execution: Execute tests simultaneously to save time.
Reporting: Generate detailed reports to track test results.
Annotations: Simplify test setup, execution, and cleanup with predefined annotations.
In this guide, we’ll explore how to install TestNG, create test cases, use annotations, configure XML files, and leverage advanced features like listeners and parameterization.
Installing and Configuring TestNG in Eclipse
Let’s start by setting up TestNG in Eclipse, a popular IDE for Java development.
Visit the Official Website:
- Go to testng.org to learn more about TestNG. The homepage describes it as a testing framework with features like annotations, data-driven testing, and flexible test execution.
Install the TestNG Plugin in Eclipse:
Open Eclipse and navigate to Help > Eclipse Marketplace.
In the search bar, type “TestNG” and press Enter.
Find TestNG for Eclipse, click Install, and follow the prompts (click Next, accept the agreement, and click Finish).
Eclipse will install the plugin in the background. Once complete (100%), you may see a security warning; click Install Anyway.
Restart Eclipse to activate the TestNG plugin.
Verify Installation:
After restarting, go to Window > Preferences.
In the search bar, type “TestNG”. If you see a TestNG option, the plugin is successfully installed. If not, repeat the installation process.
Creating a TestNG Project
Now that TestNG is installed, let’s create a new project to explore its features.
Create a Java Project:
In Eclipse, right-click in the Package Explorer and select New > Java Project.
Name the project (e.g., “TestNGTutorial”) and click Finish.
Create a Package:
Right-click on the project, select New > Package, and name it (e.g., “test”).
Packages help organize your test classes.
Create a Test Class:
Right-click on the package, select New > Class, and name it (e.g., “Day1”).
By default, Eclipse includes the public static void main method. In TestNG, you don’t need this because TestNG acts as its own compiler.
Write a Simple Test:
Remove the public static void main method.
Create a method, e.g.,
public void demo()
.Add a simple statement like
System.out.println("hello");
.Add the
@Test
annotation above the method:import org.testng.annotations.Test; public class Test1 { @Test public void demo() { System.out.println("hello"); } }
The
@Test
annotation tells TestNG that this method is a test case.
Run the Test:
Right-click the class, select Run As > TestNG Test.
The output will show “hello” along with a neat TestNG report indicating that one test passed.
Key Difference from Java
In plain Java, you need the public static void main method to run a program. Without it, the code won’t execute. TestNG eliminates this dependency by using its own compiler and annotations like @Test
, making test execution simpler and more organized.
Understanding TestNG XML Files
The TestNG XML file is the heart of a TestNG framework. It allows you to configure and control test execution, making it easier to manage large numbers of test cases.
Creating a TestNG XML File
Right-click on the project and select TestNG > Convert to TestNG.
Click Next and Finish to generate a testng.xml file.
The XML file has a hierarchical structure:
Suite: The top-level container (e.g., “Loan Department”).
Test: A module or folder within the suite (e.g., “Personal Loan”).
Classes: Java class files containing test cases.
Methods: Individual test methods within a class.
Example testng.xml:
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Loan Department">
<test name="Personal Loan">
<classes>
<class name="test.Test1"/>
<class name="test.Test2"/>
</classes>
</test>
</suite>
Running Tests via XML
Right-click the testng.xml file and select Run As > TestNG Suite.
All test cases defined in the XML will execute, and TestNG will generate a detailed report.
Benefits of XML Files
Modular Execution: Run specific modules (e.g., only “Personal Loan” test cases) by modifying the XML.
Scalability: Easily manage hundreds of test cases by adding them to the XML.
Single-Click Execution: Trigger all relevant test cases with one command.
Controlling Test Execution
TestNG provides powerful mechanisms to control which test cases run and in what order.
Grouping Test Cases
You can group test cases into categories (e.g., “smoke”, “regression”) and run only specific groups. For example, if you have 500 test cases and want to run only 40 smoke tests, TestNG can filter and execute them with a single click.
Including and Excluding Test Cases
You can include or exclude specific test methods or modules using the include and exclude tags in the XML file.
Example: Excluding a specific test method:
<test name="Car Loan">
<classes>
<class name="test.Test3">
<methods>
<exclude name="mobileLoginCar"/>
</methods>
</class>
</classes>
</test>
- This skips the
mobileLoginCar
test method while running others in the Test3 class.
Example: Including a specific test method:
<test name="Personal Loan">
<classes>
<class name="test.Test1">
<methods>
<include name="demo"/>
</methods>
</class>
</classes>
</test>
- This runs only the demo test method, excluding others in the Test1 class.
Using Regular Expressions
For large projects with many test cases, manually including or excluding each test is impractical. TestNG supports regular expressions to filter test methods based on naming conventions.
Example: Exclude all mobile-related test cases:
<test name="Car Loan">
<classes>
<class name="test.Test3">
<methods>
<exclude name="mobile.*"/>
</methods>
</class>
</classes>
</test>
- The mobile.* pattern excludes any method starting with “mobile” (e.g.,
mobileLoginCar
,mobileSignInCar
).
Tip: Follow a consistent naming convention in your framework (e.g., start all mobile test methods with “mobile”) to make filtering easier.
Running Tests by Package
You can run all test cases in a specific package without listing individual classes:
<suite name="Loan Department">
<test name="All Tests">
<packages>
<package name="test"/>
</packages>
</test>
</suite>
- This runs all test cases in the “test” package, ideal for regression testing.
TestNG Annotations
Annotations are a core feature of TestNG, allowing you to define the behavior of test methods and set up prerequisites or cleanup tasks.
Common Annotations
@Test
: Marks a method as a test case.@Test public void demo() { System.out.println("hello"); }
@BeforeTest
: Runs before all test cases in a test folder (e.g., clean the database).@BeforeTest public void setup() { System.out.println("I will execute first"); }
@AfterTest
: Runs after all test cases in a test folder (e.g., close connections).@AfterTest public void cleanup() { System.out.println("I will execute last"); }
@BeforeMethod
: Runs before each test method (e.g., initialize a browser).@AfterMethod
: Runs after each test method (e.g., close the browser).
Helper Attributes for @Test
dependsOnMethods: Specifies that a test method depends on others.
@Test(dependsOnMethods = {"webLoginCar", "mobileLoginCar"}) public void apiLoginCar() { System.out.println("API login car"); }
apiLoginCar
runs only afterwebLoginCar
andmobileLoginCar
pass.
enabled: Skips a test method if set to false.
@Test(enabled = false) public void mobileSignInCar() { System.out.println("Mobile sign in car"); }
- This skips the
mobileSignInCar
test without commenting it out.
- This skips the
timeOut: Sets a timeout for a test method (in milliseconds).
@Test(timeOut = 4000) public void slowTest() { // Test fails if it takes longer than 4 seconds }
- Useful for slow APIs or UI interactions.
Parameterization in TestNG
Parameterization allows you to run test cases with different data sets, reducing code duplication.
1. XML-Based Parameterization
You can define global or test-specific parameters in the testng.xml file.
Example: Global parameter (applies to all test folders):
<suite name="Loan Department">
<parameter name="url" value="google.com"/>
<test name="Personal Loan">
<classes>
<class name="test.Test1"/>
</classes>
</test>
</suite>
Example: Test-specific parameter:
<test name="Car Loan">
<parameter name="url" value="carloan.com"/>
<classes>
<class name="test.Test3"/>
</classes>
</test>
Accessing parameters in a test:
@Test
@Parameters("url")
public void webLoginCar(String urlName) {
System.out.println(urlName); // Prints "carloan.com"
}
You can pass multiple parameters:
<test name="Car Loan">
<parameter name="url" value="carloan.com"/>
<parameter name="username" value="123456"/>
<classes>
<class name="test.Test3"/>
</classes>
</test>
@Test
@Parameters({"url", "username"})
public void webLoginCar(String urlName, String key) {
System.out.println(urlName); // Prints "carloan.com"
System.out.println(key); // Prints "123456"
}
2. Data Provider Annotation
The @DataProvider
annotation allows you to run a test method with multiple data sets without relying on the XML file.
Example: Testing a login feature with three sets of credentials:
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class Test3 {
@DataProvider(name = "getData")
public Object[][] getData() {
Object[][] data = new Object[3][2]; // 3 rows, 2 columns
// First set
data[0][0] = "firstSetUsername";
data[0][1] = "firstPassword";
// Second set
data[1][0] = "secondSetUsername";
data[1][1] = "secondPassword";
// Third set
data[2][0] = "thirdSetUsername";
data[2][1] = "thirdPassword";
return data;
}
@Test(dataProvider = "getData")
public void mobileSignOutCar(String username, String password) {
System.out.println(username + ", " + password);
}
}
The
getData
method returns a 2D array with three rows (three test runs) and two columns (username and password).The
mobileSignOutCar
test runs three times, each with a different username and password.Output:
firstSetUsername, firstPassword secondSetUsername, secondPassword thirdSetUsername, thirdPassword
Tip: Ensure the number of parameters in the test method matches the number of columns in the data provider array.
TestNG Listeners
Listeners in TestNG monitor test execution and perform actions based on test outcomes (e.g., success, failure). They are useful for tasks like taking screenshots on test failure or logging detailed responses.
Creating a Listener
Create a new class (e.g., Listeners) that implements the
ITestListener
interface:import org.testng.ITestListener; import org.testng.ITestResult; public class Listeners implements ITestListener { @Override public void onTestSuccess(ITestResult result) { System.out.println("I successfully executed: " + result.getName()); } @Override public void onTestFailure(ITestResult result) { System.out.println("I failed executing: " + result.getName()); // Add screenshot code here for Selenium/Appium } @Override public void onTestStart(ITestResult result) {} @Override public void onStart(ITestContext context) {} @Override public void onFinish(ITestContext context) {} @Override public void onTestSkipped(ITestResult result) {} @Override public void onTestFailedButWithinSuccessPercentage(ITestResult result) {} }
Configure the listener in the testng.xml file:
<suite name="Loan Department"> <listeners> <listener class-name="testng.Listeners"/> </listeners> <test name="Personal Loan"> <classes> <class name="testng.Test1"/> </classes> </test> </suite>
Use Cases
On Failure: Capture screenshots for Selenium/Appium tests or log API responses.
On Success: Log success messages or update custom reports.
Tracking Failures: Use
result.getName()
to identify the failed test method.
Example Output (if demo test fails):
hello
I failed executing: demo
Running Tests in Parallel
TestNG allows you to run tests in parallel to reduce execution time, though this should be used cautiously to avoid performance issues.
Parallel Execution at Suite Level
To run test folders (e.g., “Personal Loan” and “Car Loan”) in parallel:
<suite name="Loan Department" parallel="tests" thread-count="2">
<test name="Personal Loan">
<classes>
<class name="test.Test1"/>
</classes>
</test>
<test name="Car Loan">
<classes>
<class name="test.Test3"/>
</classes>
</test>
</suite>
parallel="tests": Runs test folders in parallel.
thread-count="2": Allows two tests to run simultaneously.
Parallel Execution at Class Level
To run classes within a test folder in parallel:
<test name="Personal Loan" parallel="classes" thread-count="2">
<classes>
<class name="test.Test1"/>
<class name="test.Test2"/>
</classes>
</test>
Note: Parallel execution is more effective with real automation code (e.g., browser-based tests). For mobile testing (Appium), you need multiple devices/emulators. For APIs, parallel execution is feasible but may stress the server.
TestNG Reporting
After running tests, TestNG generates a report in the test-output folder:
Refresh your project in Eclipse.
Open the test-output folder and locate index.html.
Copy the file path, paste it into a browser, and view the report.
The report includes:
Summary: Number of tests passed, failed, or skipped.
Details: Failed test details (e.g., “expected true but found false” for the demo test).
Data Provider Results: Shows results for tests run with multiple data sets.
Check out the complete code repository below:
Real-World Applications
TestNG is widely used in automation frameworks for:
Selenium: Web automation (e.g., opening browsers, navigating URLs).
Appium: Mobile automation (e.g., starting the Appium server, interacting with apps).
REST API: API testing (e.g., setting base URLs, validating responses).
Example Scenarios
Database Cleanup: Use
@BeforeTest
to delete data before running loan application tests.API Setup: Set the base URL in
@BeforeTest
for REST API tests.Mobile Testing: Start the Appium server in
@BeforeTest
before executing mobile tests.Screenshot on Failure: Use listeners to capture screenshots when Selenium/Appium tests fail.
Regression Testing: Run all test cases in a package using the
<packages>
tag.
Best Practices for TestNG Frameworks
Consistent Naming Conventions: Use prefixes like “mobile” or “api” for test methods to enable easy filtering with regular expressions.
Modular Design: Organize test cases into modules (e.g., “Personal Loan”, “Car Loan”) for better control.
Avoid Hardcoding: Use XML parameters or data providers to drive data like URLs, usernames, or API keys.
Debugging: Read error messages carefully to identify and fix issues (e.g., missing quotes in XML).
Smart Use of Include/Exclude: Use include when selecting a few tests and exclude when skipping a few to minimize XML complexity.
Cautious Parallel Execution: Test parallel execution on a small scale to avoid performance issues.
Common Questions
How do you skip a test case without commenting it out?
- Use the enabled = false attribute in the
@Test
annotation.
- Use the enabled = false attribute in the
How do you achieve parameterization in TestNG?
- Use XML-based parameters for global/test-level data or the
@DataProvider
annotation for test-specific data sets.
- Use XML-based parameters for global/test-level data or the
How do you identify the failed test case in a listener?
- Use the
ITestResult
object’sgetName()
method in theonTestFailure
listener.
- Use the
Why use TestNG over plain Java?
- TestNG provides annotations, dependency management, parallel execution, and detailed reporting, which plain Java lacks.
Conclusion
TestNG is a versatile and powerful testing framework that simplifies the process of building and executing test cases in Java-based automation projects. From setting up test environments to running tests with multiple data sets, TestNG offers a wide range of features that make it indispensable for framework development.
To deepen your understanding, practice these concepts with real automation code (e.g., Selenium, Appium, or REST API tests). You can also explore advanced reporting tools like Extent Reports for more visually appealing results.
Happy testing, and stay tuned for more automation tutorials!
Subscribe to my newsletter
Read articles from Samiksha Kute directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Samiksha Kute
Samiksha Kute
Passionate Learner!