Companion code for the IT Talk "JUnit 6 vs TestNG 7". Previous edition: TestNG vs. JUnit 4 slides · TestNG vs. JUnit 4 webinar
Related projects:
- 🧪 JUnit Workshop — companion JUnit 6 examples to compare side-by-side with this repo
- 🌐 Selenium Example (JUnit 6 branch) — real-world Selenium WebDriver framework built on top of JUnit 6
- Who Is This For?
- Prerequisites
- Quick Start
- Supported Versions
- Feature Map
- Learning Path — Beginners
- Advanced Topics — Path for Senior Engineers
- Command Examples
- Project Structure
- License
- Additional Resources
- Useful Links
| Audience | What you will get |
|---|---|
| QA engineers new to TestNG | A guided tour of every major feature with runnable examples |
| Java developers migrating from JUnit 4 / JUnit 5+ | Side-by-side comparison of patterns and idioms |
| Senior / lead engineers | Deep-dives into listeners, retry strategies, parallel execution, and groups |
| Workshop facilitators | A ready-made project you can hand to attendees |
| Tool | Minimum version | Notes |
|---|---|---|
| JDK | 21 LTS | |
| Maven | 3.9+ | |
| IDE | Any (IntelliJ IDEA recommended) | Lombok plugin required for IDE support |
| Lombok plugin | Latest | IntelliJ: Settings → Plugins → Lombok |
git clone https://github.com/a-oleynik/testng-workshop.git
cd testng-workshop
mvn clean test| Library | Version used |
|---|---|
| TestNG | 7.12.0 |
| AssertJ | 3.27.7 |
| Hamcrest | 3.0 |
| Lombok | 1.18.42 |
| OpenCSV | 5.12.0 |
| SLF4J | 2.0.17 |
| Java source / target | 21 |
| Package / folder | Feature demonstrated | Test class(es) |
|---|---|---|
general |
Basic assertions (assertEquals, assertTrue, assertNull, assertSame, …) |
AssertTest |
general |
Exception testing (expectedExceptions, expectedExceptionsMessageRegExp) |
ExceptionTest |
general |
Test fixtures (@BeforeSuite, @AfterSuite, @BeforeClass, @AfterClass, @BeforeTest, @AfterTest, @BeforeMethod, @AfterMethod) |
FixturesTest |
general |
Hamcrest matchers | HamcrestTest |
general |
Timeouts (timeOut attribute on @Test) |
TimeoutTest |
general |
Disabling & skipping tests (enabled = false, SkipException) |
DisabledTest |
general |
Test descriptions (description attribute on @Test) |
DescriptionTest |
group/asserts |
Soft assertions (SoftAssert) |
SoftAssertTest |
conditional |
Assumptions via AssertJ (assumeThat) per method |
AssumeTest |
conditional |
Assumptions in @BeforeClass to skip entire class |
AssumeBeforeClassTest |
ddt |
Static inline @DataProvider |
StaticDataProviderTest |
ddt |
Dynamic CSV-file @DataProvider (Iterator-based) |
DynamicDataProviderTest |
ddt |
External @DataProvider class (dataProviderClass) |
OuterDataProviderTest |
nested |
Inner test classes grouped under a parent class | NestedTest |
grouping |
Groups (@Test(groups = …)), @BeforeGroups, @AfterGroups |
GroupTest |
dependencies |
Method & group dependencies (dependsOnMethods, dependsOnGroups) |
DependenciesTest |
execution/order |
Test execution ordering via priority attribute |
ExecutionOrderTest |
listeners |
ITestListener — observe test start, success, failure, skip |
TestListenerTest |
listeners |
IInvokedMethodListener — intercept before/after every method invocation |
MethodListenerTest |
retry |
Retry with IRetryAnalyzer + custom @Retries annotation |
RetryTest |
retry |
Retry with IAnnotationTransformer (RetryTransformer) applied globally via XML |
RetryTransformerTest |
repeat |
Repeated execution (invocationCount attribute on @Test) |
RepeatedTest |
Work through these topics in order; each builds on the previous one.
-
Basic assertions →
AssertTest
LearnassertEquals,assertTrue,assertNull,assertSame,assertNotSame, andfail. -
Test lifecycle →
FixturesTest
Understand the full TestNG fixture hierarchy:@BeforeSuite→@BeforeTest→@BeforeClass→@BeforeMethod(and theirAfter*counterparts). -
Exception testing →
ExceptionTest
UseexpectedExceptionsandexpectedExceptionsMessageRegExpon@Testto assert thrown exceptions. -
Disabling & skipping tests →
DisabledTest
Disable tests with@Test(enabled = false)or skip them dynamically by throwingSkipException. -
Test descriptions →
DescriptionTest
Add human-readable descriptions to tests with@Test(description = "…")for better report output. -
Hamcrest matchers →
HamcrestTest
Write expressive assertions withassertThat,equalTo,is,closeTo,both…and, and more. -
Soft assertions →
SoftAssertTest
Collect all assertion failures withSoftAssertbefore reporting — no early bail-out. -
Assumptions →
AssumeTest
Skip tests dynamically when preconditions aren't met using AssertJ'sassumeThat. -
Parameterized tests →
StaticDataProviderTest
Drive one test method with multiple data rows using an inline@DataProvider. -
Groups →
GroupTest
Mark tests asSmokeorRegressionand run subsets from the command line or via XML suites.
Run the whole beginner suite:
mvn clean testThese topics assume familiarity with TestNG basics.
GroupTest → grouping/ package
Assign tests to named groups. Use @BeforeGroups and @AfterGroups for group-scoped setup/teardown.
Run groups from the command line:
mvn clean test -Dgroups=Regression,SmokeOr target a specific XML suite that filters by group:
# Run only Smoke tests via XML
mvn clean test -Dsurefire.suiteXmlFiles=src/test/resources/testnggroups2.xml
# Run groups-of-groups (Smoke + Regression + Fail) via XML
mvn clean test -Dsurefire.suiteXmlFiles=src/test/resources/testnggroups1.xmlDependenciesTest → dependencies/ package
Chain tests so that a downstream test is skipped (not failed) when its upstream dependency fails, using dependsOnMethods or dependsOnGroups.
DynamicDataProviderTest, OuterDataProviderTest → ddt/ package
- Load test data lazily from CSV files via an
Iterator-based@DataProvider. - Separate data-provider logic into a dedicated
MyDataProviderclass and reference it withdataProviderClass. - Use the custom
@DataSource(path = "…")annotation to bind a CSV file path to a test method at runtime.
NestedTest → nested/ package
Group related scenarios (Multiply, Divide, Add) as public inner classes inside a parent class. Run them via testnested.xml:
mvn clean test -Dsurefire.suiteXmlFiles=src/test/resources/testnested.xmlExecutionOrderTest → execution/order/ package
Control method execution order with the priority attribute on @Test (lower value = earlier execution). Methods without a priority run before prioritized ones.
TestListenerTest, MethodListenerTest → listeners/ package
ITestListener(MyTestListener) — react to test start, success, failure, and skip events. Ideal for screenshot capture on failure.IInvokedMethodListener(MyMethodListener) — intercept every method invocation (including@Before*/@After*).TestListenerAdapter(MyExtendedTestListener) — extend the adapter and override only the callbacks you need.
Attach listeners declaratively with@Listeners(value = MyTestListener.class)or globally via atestng.xml<listeners>block.
RetryTest — IRetryAnalyzer + custom @Retries(limit = N) annotation applied per test method
RetryTransformerTest — IAnnotationTransformer (RetryTransformer) injects RetryAnalyzer globally for every test in the suite without touching test source code
Run the transformer-based retry suite:
mvn clean test -Dsurefire.suiteXmlFiles=src/test/resources/testngretrylistener.xmlConfigured globally in pom.xml via Surefire:
<parallel>methods</parallel>
<threadCount>3</threadCount>Tests run concurrently by default. Fine-tune parallelism per suite with parallel="classes" or parallel="tests" and a custom thread-count in any testng.xml.
All suite XML files live in src/test/resources/. They demonstrate:
| File | What it shows |
|---|---|
testng1.xml |
Include / exclude specific test methods per class |
testng2.xml |
Run a fixed set of classes in parallel |
testnggroups1.xml |
Groups-of-groups — combine named groups under one alias |
testnggroups2.xml |
Include only the Smoke group |
testngretrylistener.xml |
Register RetryTransformer listener globally |
testnested.xml |
Run all tests from a package (including inner classes) |
Run any suite directly:
mvn clean test -Dsurefire.suiteXmlFiles=src/test/resources/testng1.xmlmvn clean surefire-report:report
# or
mvn clean siteReports are written to
target/site/surefire-report.html
mvn clean testReports are written to:
- Surefire report:
target/surefire-reports/index.html- TestNG emailable report:
target/surefire-reports/emailable-report.html
mvn clean test -Dtest=AssertTestmvn clean test -Dtest=AssertTest#assert_equals_multiplication_testmvn clean test -Dtest=AssertTest,HamcrestTestmvn clean test -Dtest=AssertTest#assert_equals*mvn clean test -Dtest=AssertTest#assert_equals*+assert_boolean*mvn clean test -Dgroups=Regression,Smokemvn clean test -Dsurefire.suiteXmlFiles=src/test/resources/testng1.xmlmvn clean installmvn clean install -DskipTestsmvn clean surefire-report:reportSurefire report is written to:
- Surefire report:
target/reports/surefire.html
mvn clean test -Xsrc/
├── main/java/com/oleynik/qa/workshop/testng/
│ ├── model/ # Domain model (User, MyDoubleWrapper)
│ ├── annotations/ # Custom annotations (@Retries, @DataSource)
│ ├── dataproviders/ # Reusable data provider (MyDataProvider)
│ ├── listeners/ # ITestListener, IInvokedMethodListener, IAnnotationTransformer
│ ├── retry/ # IRetryAnalyzer implementation (RetryAnalyzer)
│ ├── Factorial.java # Utility class used by data-driven tests
│ └── Utils.java # Shared test utilities (e.g. waitFor)
└── test/java/com/oleynik/qa/workshop/testng/
├── general/ # Core assertions, fixtures, exceptions, descriptions, timeouts
├── group/asserts/ # Soft assertions
├── conditional/ # Assumptions (AssertJ assumeThat)
├── ddt/ # Data-driven tests (@DataProvider, CSV, external provider)
├── nested/ # Inner-class test grouping
├── grouping/ # TestNG groups (@Test(groups = …))
├── dependencies/ # Test dependencies (dependsOnMethods / dependsOnGroups)
├── execution/order/ # Test execution ordering (priority)
├── listeners/ # Tests demonstrating listener hooks
├── retry/ # Retry strategies (IRetryAnalyzer, IAnnotationTransformer)
└── repeat/ # Repeated execution (invocationCount)
This project is licensed under the MIT License — see the LICENSE file for details.
- TestNG Documentation
- TestNG GitHub
- AssertJ Documentation
- Hamcrest Tutorial
- Lombok Features
- OpenCSV Documentation
- Maven Surefire Plugin
- Maven Surefire Report Plugin
- JUnit Workshop — companion JUnit 6 examples
- Selenium Example — real-world Selenium framework using TestNG
- Java Download: https://www.oracle.com/java/technologies/downloads/
- Maven Download: https://maven.apache.org/download.cgi
- TestNG Releases: https://github.com/testng-team/testng/releases
- Lombok Download: https://projectlombok.org/download
- IntelliJ Lombok Plugin: https://plugins.jetbrains.com/plugin/6317-lombok
- JUnit Workshop: https://github.com/a-oleynik/junit-workshop
- Selenium Example: https://github.com/a-oleynik/selenium-example