skip to content

TestNG Wiring

Wiring TestNG with useTestNG and configuring its suites, groups, and discovery options. Comes up in codebases that never moved to JUnit and still need someone who can read the build.

on this pageshow

questions

5

How do you configure a Gradle project to run tests with TestNG instead of the default JUnit?

level: juniorimportance: must knowfreq 55%

answer

  1. testImplementation org.testng:testng
  2. useTestNG() on Test task
  3. not the default — JUnit is
  4. forgot useTestNG() => 0 tests run
  5. siblings: useJUnit / useJUnitPlatform

basics

~10 s

Add the TestNG dependency to testImplementation, then call useTestNG() inside the test task. Without useTestNG(), Gradle assumes JUnit and won't detect @Test annotations from TestNG.

solid answer

~40 s

TestNG support is built into Gradle's `Test` task, but it is not the default — Gradle uses JUnit Platform or JUnit 4 unless told otherwise. Two things are required: (1) declare the runtime/compile dependency with `testImplementation("org.testng:testng:7.x")`, and (2) switch the test framework by calling `useTestNG()` on the `test` task. The dependency puts TestNG annotations on the test classpath so your code compiles; `useTestNG()` tells Gradle's test executor to load TestNG's runner and scan for `org.testng.annotations.Test` rather than JUnit's `@Test`. If you only add the dependency but forget `useTestNG()`, the build runs but reports zero tests because Gradle's default detector ignores TestNG annotations. The call also gives you a configuration closure for suites, groups, and parallelism.

code

kotlin · 7 lines
kotlin
dependencies {
    testImplementation("org.testng:testng:7.9.0")
}

tasks.named<Test>("test") {
    useTestNG()
}

go deeper

for a junior

Name the two steps: testImplementation dependency + useTestNG() on the test task.

for a middle

Explain why both are required and call out the silent 0-tests failure when useTestNG() is missing.

for a senior

Discuss that the Test task is framework-singular, the useJUnit/useJUnitPlatform siblings, and the TestNGOptions closure exposed.

for a principal

Frame framework selection as a per-Test-task decision and how multiple source sets / Test tasks let a codebase mix frameworks cleanly during migrations.

## Why two steps are needed Gradle's `Test` task is framework-agnostic at the API level but ships with a default test framework. For modern projects that default is JUnit (Platform or 4), so simply putting TestNG on the classpath is **not** enough — Gradle's class detector looks for the framework it has been told to use. You must explicitly opt into TestNG. ### Step 1 — the dependency TestNG annotations (`@Test`, `@BeforeMethod`, `@DataProvider`, ...) live in the `org.testng:testng` artifact. Declare it on the `testImplementation` configuration so it is available both to compile the test sources and at test runtime: ```kotlin testImplementation("org.testng:testng:7.9.0") ``` ### Step 2 — switch the framework Call `useTestNG()` on the `Test` task. This replaces the framework backing the task with `TestNGTestFramework`, which knows how to instantiate TestNG's runner and how to detect TestNG-annotated classes: ```kotlin tasks.named<Test>("test") { useTestNG() } ``` The sibling methods are `useJUnit()` (JUnit 4) and `useJUnitPlatform()` (JUnit 5). Only one framework backs a given `Test` task. ## The classic failure mode If you add the dependency but omit `useTestNG()`, the build still **succeeds** — but the test report shows `0 tests`. Gradle's default JUnit detector simply never matches TestNG's annotations, so nothing runs and nothing fails. This silent pass is the single most common TestNG-wiring bug. ## What useTestNG() unlocks The method accepts a configuration action exposing `TestNGOptions`, where you configure suite XML files, included/excluded groups, parallel execution, listeners, and more. So the same call that enables TestNG is also the entry point for all TestNG-specific tuning.

  • Your build is green but the report says 0 tests ran. What is the most likely cause with TestNG?
    You added the org.testng dependency but never called useTestNG(), so Gradle's default JUnit detector ignored the TestNG @Test annotations and discovered nothing.
  • Can a single Test task run both JUnit and TestNG tests?
    No. A Test task is backed by exactly one framework. Use separate Test tasks (or source sets) if you genuinely need both.

saying these in an interview costs you the question

  • Claiming TestNG is auto-detected just by adding the dependency.
  • Saying useTestNG() and useJUnitPlatform() can both apply to the same Test task.
  • Putting TestNG on `implementation` instead of `testImplementation`.

context

open as a page

How do you include or exclude TestNG groups from Gradle, and what does that control?

level: middleimportance: should knowfreq 45%

basics

~10 s

Inside useTestNG { ... } call includeGroups("smoke") and excludeGroups("slow"). TestNG groups are named tags on @Test methods, and these options select which tagged tests run.

open as a page

How do you point Gradle at a TestNG suite XML file, and when would you prefer suite-XML-driven discovery over Gradle's class detection?

level: middleimportance: should knowfreq 38%

basics

~10 s

Inside useTestNG { } call suites(file("src/test/resources/testng.xml")). Gradle then runs the tests listed in that XML, letting TestNG control ordering, grouping, and parallel config instead of Gradle's own class scan.

open as a page

What TestNGOptions can you set from Gradle to control parallel execution and behavior, and how do they relate to Gradle's own maxParallelForks?

level: seniorimportance: should knowfreq 30%

basics

~10 s

Inside useTestNG { } you can set parallel = "methods", threadCount = N, plus listeners, preserveOrder, and useDefaultListeners. These run tests concurrently within one JVM, separate from Gradle's maxParallelForks which spawns multiple test JVMs.

open as a page

A legacy module uses TestNG and you're introducing JUnit 5 for new tests. How do you let both run under Gradle, and what are the constraints?

level: seniorimportance: nice to knowfreq 22%

basics

~20 s

A single Test task supports only one framework, so create a second source set with its own Test task: keep useTestNG() on the original, add useJUnitPlatform() on the new one. Wire the new task into check.

open as a page