What is TestNG?
Java testing framework inspired by JUnit/NUnit but designed for end-to-end, integration, and UI tests.
What is TestNG?
TestNG is an open-source Java testing framework created by Cédric Beust in 2004 to address gaps in JUnit 3 (which was the dominant Java test framework at the time). The name stands for "Test Next Generation". TestNG was designed not just for unit tests but for the broader testing pyramid: integration tests, end-to-end tests, UI tests with Selenium, and performance tests. While JUnit has caught up considerably with JUnit 5 (Jupiter), TestNG remains the dominant choice for Selenium-based UI testing and large enterprise Java test suites.
If your team is doing functional QA on Java applications — especially with Selenium WebDriver, REST Assured, or similar tools — there's a high chance you're using TestNG. The combination of TestNG + Selenium + Maven + Jenkins remains the canonical Java QA stack at most enterprises.
What TestNG offers that JUnit didn't (originally)
The original differentiators (some now matched by JUnit 5):
- Annotation-driven configuration —
@Test,@BeforeMethod,@AfterClass,@DataProvider,@Listenersinstead of subclassing TestCase. - Test groups — tag tests with
@Test(groups = {"smoke", "regression"})and run subsets via XML configuration. Foundational for layered test suites. - Dependent tests —
@Test(dependsOnMethods = "login")declares execution order. Controversial (unit tests should be independent) but useful for end-to-end flows. - Data providers — parameterized tests with
@DataProvider. Run the same test method with N different inputs. - Parallel execution — at multiple granularities (suite, test, class, method) configured in
testng.xml. The killer feature for slow Selenium suites. - XML test configuration — define test suites declaratively in XML. Run different combinations of tests without recompiling.
- Listeners and reporters — extension points for custom logging, screenshots on failure (Selenium), and custom HTML reports.
The canonical TestNG test class
import org.testng.annotations.*;
import static org.testng.Assert.*;
public class CalculatorTest {
private Calculator calc;
@BeforeMethod
public void setUp() {
calc = new Calculator();
}
@Test(groups = {"smoke"})
public void shouldAddTwoNumbers() {
assertEquals(calc.add(2, 3), 5);
}
@Test(dataProvider = "divisionData")
public void shouldDivide(int a, int b, int expected) {
assertEquals(calc.divide(a, b), expected);
}
@DataProvider
public Object[][] divisionData() {
return new Object[][] {
{10, 2, 5},
{20, 4, 5},
{100, 10, 10}
};
}
}TestNG vs. JUnit 5 (the honest 2026 comparison)
| Feature | TestNG | JUnit 5 |
|---|---|---|
| Annotations | Mature, comprehensive | Mature in Jupiter |
| Parallel execution | Built-in, easy config | Available, more setup |
| Parameterized tests | @DataProvider | @ParameterizedTest |
| Test groups/tags | @Test(groups=...) | @Tag |
| Dependent tests | Yes | No (by design) |
| XML suite config | testng.xml | None native |
| Selenium ecosystem | Dominant choice | Increasing adoption |
| Spring/REST Assured | Excellent integration | Excellent integration |
| Modern Java (records, sealed) | Compatible | Compatible |
The pragmatic call: JUnit 5 for unit tests, TestNG for end-to-end and Selenium. Mixing both in one project is fine.
TestNG and Selenium WebDriver
The reason TestNG stays popular: Selenium UI tests are slow, flaky, and require careful orchestration. TestNG features that solve this:
- Parallel browser execution. Run 10 Chrome instances in parallel against your test suite. Cuts wall-clock time dramatically.
- Retry analyzers. Implement
IRetryAnalyzerto automatically retry failed tests N times. Tames flakiness in Selenium. - Listeners for screenshots. Implement
ITestListener.onTestFailureto capture a screenshot whenever any test fails — useful for debugging UI flakes. - Group-based runs. Run smoke tests on every commit, full regression nightly, all controlled via testng.xml.
- BeforeSuite browser setup. Open WebDriver once per suite (not per test) to amortize browser startup cost.
Common TestNG pitfalls
- Inter-test dependencies via shared state. Tests that pass when run alone but fail in a suite usually share static fields. Each test should be independent.
- Parallel execution race conditions. WebDriver instances per thread, not per class. Use ThreadLocal<WebDriver> or Selenium's
SeleniumGrid. - Hardcoded waits.
Thread.sleep(5000)kills test speed. Use Selenium'sWebDriverWaitwith explicit conditions. - testng.xml drift. XML configuration grows unwieldy. Keep it simple: define groups, point at packages, let TestNG discover tests.
- Over-using dependsOnMethods. Long dependency chains create cascading failures. One failure cancels 10 downstream tests, hiding the original signal.
- No retry budget. Retrying flaky tests forever masks real bugs. Cap retries at 2-3 and investigate anything that retries consistently.
Running TestNG: from CLI to CI
- Maven Surefire/Failsafe — standard for TestNG in Maven projects.
mvn testruns unit tests;mvn verifyruns integration tests via Failsafe. - Gradle —
useTestNG()in test config; otherwise standard. - IntelliJ IDEA / Eclipse — first-class TestNG support; right-click any test → Run.
- CI (Jenkins, GitHub Actions, GitLab) — invoke via Maven/Gradle, archive testng-results.xml + custom HTML reports.
- Docker — common pattern for Selenium: Selenoid or Selenium Grid in Docker, TestNG runs in CI hitting the grid.
FAQ: TestNG
Should I use TestNG or JUnit 5 for new projects?
For unit tests in greenfield projects, JUnit 5 — it's the default in Spring Boot and most modern Java tooling. For Selenium-heavy QA suites, TestNG — better parallel execution and ecosystem fit. Many projects use both.
Is TestNG still actively maintained?
Yes. TestNG had a major 7.x release line (current as of 2026); active maintenance and Java 21+ compatibility. Cédric Beust still champions it.
Can TestNG run JUnit tests?
Yes. TestNG can wrap JUnit tests via junit="true" in testng.xml. Useful during gradual migrations. JUnit 5 cannot directly run TestNG tests.
How do I run TestNG tests in parallel?
In testng.xml: <suite parallel="methods" thread-count="4">. Granularities: suite, tests, classes, methods, instances. Methods is most fine-grained but requires fully independent tests.
What's a TestNG "group"?
A tag on a test method. @Test(groups = {"smoke", "regression"}). Run via testng.xml: <groups><run><include name="smoke"/></run></groups>. Letting you split test suites into smoke (fast) and regression (slow) without separate test classes.
What about TestNG with Spring Boot?
Use spring-test with TestNG via @ContextConfiguration + AbstractTestNGSpringContextTests. Spring Boot defaults to JUnit 5; you can switch to TestNG by replacing dependencies. Spring's docs cover both.
How LoadFocus relates to TestNG and Java load testing
TestNG covers functional Java testing; for load testing the same Java applications, JMeter is the canonical tool. LoadFocus JMeter cloud testing runs your existing .jmx files at scale across 25+ regions without you managing JMeter infrastructure. Use TestNG for functional regression, JMeter for capacity validation, and API monitoring for production observability.
Related LoadFocus Tools
Put this concept into practice with LoadFocus — the same platform that powers everything you just read about.