skip to content

What test framework does a Gradle Test task use if you never call any use*() selector, and how has that interacted with the JVM test-suite plugin?

level: middleimportance: should knowfreq 55%

answer

  1. raw Test task default = JUnit 4
  2. jvm-test-suite default = Jupiter
  3. testing { suites { } } DSL
  4. useJUnitJupiter on the suite
  5. java plugin auto-applies test-suite

basics

~10 s

By default a raw Test task uses JUnit 4. But the modern jvm-test-suite plugin (applied by the java plugin) defaults its built-in 'test' suite to useJUnitJupiter(), so JUnit 5 is the default there.

solid answer

~40 s

It depends on how the task is created. A bare `Test` task, configured directly, defaults to **JUnit 4** — that's the historical Gradle default and why `useJUnitPlatform()` was needed everywhere. Since Gradle 7, the **`jvm-test-suite`** plugin (auto-applied by the `java` plugin) models tests as **test suites**. Its built-in `test` suite defaults to **JUnit Jupiter** via `useJUnitJupiter()`. So in a modern `java`/`java-library` project you can often get JUnit 5 without writing `useJUnitPlatform()` at all — the suite configures it and pulls the Jupiter dependency for you: ```kotlin testing { suites { val test by getting(JvmTestSuite::class) { useJUnitJupiter("5.10.2") } } } ``` Knowing both models matters: legacy build scripts configure `tasks.test { ... }` directly (JUnit 4 default), while newer ones drive the framework through the `testing { suites { ... } }` block (Jupiter default).

code

kotlin · 7 lines
kotlin
testing {
    suites {
        val test by getting(JvmTestSuite::class) {
            useJUnitJupiter("5.10.2")
        }
    }
}

go deeper

for a junior

Just know the raw Test task defaults to JUnit 4 and you opt into 5 with useJUnitPlatform().

for a middle

Explain both defaults: JUnit 4 for the bare task, Jupiter for the jvm-test-suite's built-in test suite, and the suite selectors.

for a senior

Discuss migrating legacy tasks.test { } configuration to the suite DSL and how the suite auto-wires dependencies and the launcher.

for a principal

Set an org-wide policy: prefer the suite DSL so JUnit 5 is the default and dependency wiring is consistent across all modules, eliminating ad-hoc useJUnitPlatform() calls.

## Two layers, two defaults The `Test` **task** and the `jvm-test-suite` **plugin** are different abstractions, and they have different defaults — this is the crux of the question. ### The Test task default The Gradle `Test` task type, configured directly, has always defaulted to **JUnit 4** when you call no selector. That legacy default is exactly why countless build scripts contain `useJUnitPlatform()` — it's the explicit opt-in to JUnit 5. ### The jvm-test-suite plugin Gradle 7 introduced the `jvm-test-suite` plugin, applied automatically by the `java` plugin. It introduces a `testing { suites { ... } }` DSL where each suite is a `JvmTestSuite`. The built-in suite named `test` **defaults to `useJUnitJupiter()`** — i.e. JUnit 5. The suite also wires the corresponding dependencies (`junit-jupiter`, the platform launcher) onto the suite's dependency scope for you, so you don't list them manually. ### Suite-level framework selectors On a `JvmTestSuite` you choose the framework with suite methods, not the task methods: - `useJUnitJupiter()` / `useJUnitJupiter("5.10.2")` — JUnit 5 (the suite default). - `useJUnit()` / `useJUnit("4.13.2")` — JUnit 4. - `useTestNG()` — TestNG. - `useSpock()` / `useKotlinTest()` — convenience for those frameworks. Under the hood the suite configures the underlying `Test` task's framework, so the two layers ultimately agree. ### Why this trips people up A developer reading `tasks.named<Test>("test")` sees a JUnit-4-default task; a developer reading the `testing` block sees a Jupiter-default suite. The same project can show both. The safe mental model: **if you use the suite DSL, the default is JUnit 5; if you configure the raw task and say nothing, it's JUnit 4.** ```kotlin // Suite DSL (modern) — Jupiter by default testing { suites { val test by getting(JvmTestSuite::class) { // useJUnitJupiter() is already the default } } } ```

  • Where do you pass the framework version — on the task selector or the suite selector?
    On the suite selector: useJUnitJupiter("5.10.2"). The Test task's useJUnitPlatform() takes no version; it relies on whatever Jupiter is on the classpath.
  • Why does the suite DSL let you skip declaring junit-jupiter dependencies manually?
    Calling useJUnitJupiter() on the JvmTestSuite wires the matching Jupiter and platform-launcher dependencies onto the suite's implementation/runtime scope automatically.

saying these in an interview costs you the question

  • Asserting the raw Test task defaults to JUnit 5 — it defaults to JUnit 4.
  • Confusing useJUnitPlatform() (task, no version) with useJUnitJupiter() (suite, takes a version).

context