TestNG ◆ Java Selenium ◆ Aayush Mishra ◆ SDET ◆ @Test @BeforeMethod @AfterMethod ◆ Parallel Execution ◆ Data Providers ◆ Maven Integration ◆ TestNG ◆ Java Selenium ◆ Aayush Mishra ◆ SDET ◆ @Test @BeforeMethod @AfterMethod ◆ Parallel Execution ◆ Data Providers ◆ Maven Integration ◆
Java Testing Framework

TESTNG
SELENIUM
MASTERY

Version 7.9.0 · Java 17+ · Selenium 4.x

The complete guide to enterprise-grade test automation with TestNG and Selenium WebDriver. Annotations, parallel execution, data providers, and Maven integration — built by Aayush Mishra, SDET.

Live Test Suite · LoginTests.java
LoginTests RUNNING
✓ testValidLogin() 0.42s
✓ testInvalidPassword() 0.38s
✓ testEmptyCredentials() 0.31s
◌ testRememberMe() ...
– testSSOLogin() skipped
SearchTests PASSED
✓ testSearchByKeyword() 0.55s
✓ testSearchFilters() 0.62s
✗ testSearchAutoComplete() 1.2s
24Tests
21Passed
1Failed
2Skipped

01 What is TestNG

TEST NEXT
GENERATION.

TestNG is a powerful Java testing framework inspired by JUnit and NUnit, designed for modern enterprise test automation at scale.

The framework that powers enterprise Java test automation.

TestNG (Test Next Generation) was created by Cédric Beust to overcome JUnit's limitations. It introduces powerful features like annotations, data-driven testing, parallel execution, grouping, and dependency management — all essential for enterprise-scale Selenium automation.

When combined with Selenium WebDriver, TestNG becomes the backbone of professional QA pipelines — from simple smoke tests to complex cross-browser parallel regression suites running across 50+ test cases simultaneously.

Used by teams at Google, LinkedIn, and thousands of enterprise QA departments worldwide, TestNG integrates seamlessly with Maven, Jenkins, Allure Reports, and every major CI/CD platform.

LoginTest.java
import org.testng.annotations.*;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.*;

public class LoginTest {

    private WebDriver driver;

    @BeforeMethod
    public void setUp() {
        driver = new ChromeDriver();
        driver.get("https://example.com/login");
    }

    @Test(groups = "smoke", priority = 1)
    public void testValidLogin() {
        driver.findElement(By.id("username")).sendKeys("admin");
        driver.findElement(By.id("password")).sendKeys("secret");
        driver.findElement(By.id("loginBtn")).click();
        Assert.assertTrue(driver.getTitle().contains("Dashboard"));
    }

    @AfterMethod
    public void tearDown() {
        driver.quit();
    }
}
🧪
Annotation-Driven
Replace verbose JUnit setup with clean, declarative annotations. @Test, @BeforeMethod, @AfterClass — every test lifecycle controlled with precision.
⚡
Parallel Execution
Run test suites, classes, or individual tests in parallel via testng.xml — cutting suite execution time from hours to minutes.
📊
Data Providers
Drive parameterized tests with @DataProvider — feed hundreds of data combinations to a single test method without code duplication.
🔗
Test Dependencies
Define test execution order and dependencies with dependsOnMethods — ensuring prerequisite tests pass before dependent ones run.
02 Core Annotations

@ANNOTATIONS
DECODED.

Every TestNG annotation explained — what it does, when to use it, and how it maps to the Selenium test lifecycle.

@T
@Test
Marks a method as a test case
The core annotation. Any public method annotated with @Test becomes a test case. Supports priority, groups, enabled, expectedExceptions, timeOut, and dependsOnMethods parameters.
@Test(priority=1, groups="smoke", timeOut=5000)
@BS
@BeforeSuite
Runs once before the entire suite
Perfect for global setup: initializing WebDriverManager, setting system properties, configuring logging, or establishing database connections used across all test classes.
@BeforeSuite — global driver config
@AS
@AfterSuite
Runs once after the entire suite
Ideal for global teardown: generating final reports, closing database connections, sending Slack/email notifications, or archiving test artifacts to S3.
@AfterSuite — generate Allure report
@BC
@BeforeClass
Runs once before any test in the class
Used to initialize class-level resources shared across all tests in a class — opening browser once per class instead of per test for performance optimization.
@BeforeClass — open browser once
@AC
@AfterClass
Runs once after all tests in the class
Closes class-level resources: driver.quit() at class level, clearing test data inserted during the class, or generating class-level screenshots.
@AfterClass — driver.quit()
@BM
@BeforeMethod
Runs before every test method
The most commonly used lifecycle hook. Creates fresh browser state before each test — navigating to start URL, clearing cookies, resetting application state.
@BeforeMethod — fresh browser state
@AM
@AfterMethod
Runs after every test method
Takes screenshot on failure, closes popups, resets session state. Receives ITestResult parameter to check test status and trigger conditional teardown logic.
@AfterMethod — screenshot on failure
@DP
@DataProvider
Supplies parameterized test data
Returns Object[][] to feed multiple data combinations to a single @Test method. Can be defined in a separate utility class and referenced by name across any test in the project.
@DataProvider(name="loginData")
@P
@Parameters
Injects values from testng.xml
Reads parameter values defined in testng.xml at runtime — perfect for browser type, environment URL, username, and any config that varies between test runs or environments.
@Parameters({"browser","url"})
03 System Architecture

THE STACK
EXPLAINED.

How TestNG, Selenium, Maven, and your CI/CD pipeline connect into a single enterprise test automation system.

01
Test Classes (Java)
Your @Test methods, Page Object Model classes, and utility helpers written in Java
02
TestNG Framework
Reads testng.xml, manages lifecycle hooks, executes tests in configured order/parallel
03
Selenium WebDriver
Issues commands to browser drivers — ChromeDriver, GeckoDriver, EdgeDriver
04
WebDriverManager
Automatically downloads and configures the correct browser driver binary
05
Browser (Chrome/Firefox)
Real browser instance executing UI interactions against the target application
06
Maven + Surefire Plugin
Builds project, resolves dependencies, triggers TestNG via mvn test
07
Allure / ExtentReports
Generates rich HTML reports with screenshots, logs, and failure analysis
08
Jenkins / GitHub Actions
CI/CD pipeline trigger — runs full suite on every commit or PR
Layer 1–2 · Tests + TestNG
The Test Brain
Your Java test classes define the what. TestNG's engine reads testng.xml to determine the how — execution order, parallel threading, group filtering, and which lifecycle hooks fire around each test.
Layer 3–5 · Selenium + Browser
The Automation Arm
Selenium WebDriver translates Java commands into browser-native DevTools Protocol (CDP) calls. WebDriverManager eliminates the manual driver download problem — it detects your browser version and fetches the matching driver automatically.
Layer 6 · Maven Build
The Build System
Maven's pom.xml declares all dependencies (TestNG, Selenium, WebDriverManager, Allure). The maven-surefire-plugin reads your testng.xml during the test phase — making every build deterministic and portable across machines.
Layer 7–8 · Reports + CI/CD
The Feedback Loop
Allure or ExtentReports generate interactive HTML reports with step-level screenshots, execution timelines, and failure stacks. Jenkins or GitHub Actions consume these reports, publish results, and gate PRs on test pass rate thresholds.
testng.xml — Suite Configuration
testng.xml
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">

<suite name="RegressionSuite" parallel="methods" thread-count="4">

    <!-- Global parameters available to all tests -->
    <parameter name="browser"  value="chrome"  />
    <parameter name="baseUrl"  value="https://staging.app.com"  />

    <!-- Run smoke tests first -->
    <test name="SmokeTests">
        <groups>
            <run><include name="smoke" /></run>
        </groups>
        <classes>
            <class name="tests.LoginTest"   />
            <class name="tests.SearchTest"  />
        </classes>
    </test>

    <!-- Full regression in parallel -->
    <test name="RegressionTests">
        <classes>
            <class name="tests.CheckoutTest"  />
            <class name="tests.ProfileTest"   />
            <class name="tests.PaymentTest"   />
        </classes>
    </test>

</suite>
@DataProvider — Parameterized Tests
LoginDataTest.java
@DataProvider(name = "loginCredentials")
public Object[][] loginData() {
    return new Object[][] {
        { "admin@co.com",   "Admin@123",  true  },  // valid
        { "user@co.com",    "wrongPass",  false },  // invalid pass
        { "",               "",           false },  // empty fields
        { "sql' OR '1'='1", "anything",  false },  // SQL injection
    };
}

@Test(dataProvider = "loginCredentials")
public void testLogin(String email, String pass, boolean expected) {
    // TestNG runs this method 4 times — once per data row
    loginPage.login(email, pass);
    Assert.assertEquals(loginPage.isLoggedIn(), expected);
}
04 TestNG vs JUnit

TESTNG
WINS.

Legacy
JUnit 5
  • ✕ No built-in parallel execution at method level
  • ✕ No native data provider mechanism
  • ✕ No test grouping/filtering out of the box
  • ✕ No dependsOnMethods for test ordering
  • ✕ No XML-driven suite configuration
  • ✕ Limited reporting listeners
  • ✕ No built-in retry failed tests support
VS
Preferred
TestNG 7.x
  • ✓ Native parallel at suite/class/method/test level
  • ✓ @DataProvider for parameterized testing
  • ✓ @Test(groups="smoke") for granular filtering
  • ✓ dependsOnMethods and dependsOnGroups
  • ✓ testng.xml for full suite orchestration
  • ✓ ITestListener, IReporter custom hooks
  • ✓ IRetryAnalyzer for flaky test management
05 Interactive Runner

TEST
RUNNER.

Simulate running a TestNG test class. Select a test type, enter a class name, and watch the console output — exactly as you'd see in your IDE or CI pipeline.

Test Configuration
Quick Scenarios
testng-runner · console output
idle
00:00:00INFOTestNG runner ready · Select a test type and click ▶ Run TestNG
0 / 0 tests0%
06 Setup Guide

ZERO TO
RUNNING
IN MINUTES.

01
Java 17 + Maven
Install Java 17 JDK and Apache Maven. Verify installation in terminal.
java -version && mvn -version
02
Create Maven Project
Generate a new Maven project with standard directory structure.
mvn archetype:generate -DgroupId=com.tests
03
Add pom.xml Dependencies
Add TestNG, Selenium, WebDriverManager to your pom.xml dependencies section.
testng 7.9.0 + selenium-java 4.x
04
Configure Surefire Plugin
Add maven-surefire-plugin pointing to your testng.xml in the build section.
<suiteXmlFile>testng.xml</suiteXmlFile>
05
Create testng.xml
Define your test suite, parallel mode, thread count, and test classes.
parallel="methods" thread-count="4"
06
Write First @Test
Create a test class with @BeforeMethod, @Test, and @AfterMethod annotations.
src/test/java/tests/LoginTest.java
07
Install ChromeDriver
WebDriverManager handles this automatically — just add it as a dependency.
WebDriverManager.chromedriver().setup()
08
Run Your Suite
Execute the full suite via Maven. Reports generated in target/surefire-reports.
mvn clean test
pom.xml — Core Dependencies
pom.xml
<dependencies>

    <!-- TestNG -->
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.9.0</version>
    </dependency>

    <!-- Selenium WebDriver -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.18.1</version>
    </dependency>

    <!-- WebDriverManager (auto driver setup) -->
    <dependency>
        <groupId>io.github.bonigarcia</groupId>
        <artifactId>webdrivermanager</artifactId>
        <version>5.7.0</version>
    </dependency>

    <!-- Allure TestNG Reporter -->
    <dependency>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-testng</artifactId>
        <version>2.25.0</version>
    </dependency>

</dependencies>
07 Best Practices

WRITE TESTS
THAT LAST.

Production-grade TestNG patterns used by senior SDETs at top engineering teams worldwide.

01
🏗️
Page Object Model
Never put locators in test methods. Every page gets its own class with @FindBy fields and action methods. Tests read like English — loginPage.login(user, pass) — not driver.findElement(By.id("usr")).
Architecture
02
🧵
ThreadLocal WebDriver
For parallel execution, store WebDriver in ThreadLocal<WebDriver>. Each thread gets its own driver instance — preventing race conditions and test pollution when running methods in parallel.
Parallel Safety
03
📸
Screenshot on Failure
Implement ITestListener and capture a screenshot in onTestFailure(). Attach it to Allure with @Attachment. Never let a test fail silently — always have visual evidence of what went wrong.
Debugging
04
🔁
IRetryAnalyzer
Implement IRetryAnalyzer to retry flaky tests automatically (max 2 retries). Mark genuinely flaky tests with @Test(retryAnalyzer=RetryAnalyzer.class) rather than letting them block your CI pipeline.
Stability
05
⏱️
Explicit Waits Only
Ban Thread.sleep() from your codebase. Use WebDriverWait with ExpectedConditions exclusively. Fluent waits with custom polling intervals for dynamic elements. Set a project-wide implicit wait of zero to avoid conflicts.
Reliability
06
🏷️
Meaningful Test Groups
Tag every test with at least one group: "smoke", "regression", "api", "ui", "critical". Run only smoke tests on every commit, full regression nightly. testng.xml group filters make this effortless to configure per environment.
Organisation