skip to content

The built-in `test` suite and a custom integrationTest suite are both JvmTestSuites. How do you reconfigure the built-in one through the same DSL, and how does that relate to registering a new suite?

level: middleimportance: should knowfreq 35%

answer

  1. getting = existing test suite
  2. registering = new suite
  3. both JvmTestSuite in one container
  4. named() vs register()
  5. only test auto-joins check

basics

~20 s

Use getting instead of registering for the existing test suite: val test by getting(JvmTestSuite::class) { useJUnitJupiter() }. A new suite uses registering because it doesn't exist yet; the built-in test already exists, so you fetch and configure it.

solid answer

~30 s

Both are `JvmTestSuite` instances in the same `testing.suites` container. The built-in `test` suite is created by the plugin, so in the Kotlin DSL you access it with the `getting` delegate (or `suites.named("test")`); your `integrationTest` is brand new, so you use `registering` (or `suites.register(...)`). Practically this lets you set the framework on `test` (`useJUnitJupiter()`) right beside declaring `integrationTest` with the same syntax, keeping all test configuration in one block. The symmetry is the design point: once `integrationTest` exists, it behaves exactly like `test` — same task/source-set/configuration derivation — differing only in being registered rather than pre-existing and in not auto-joining `check`.

code

kotlin · 10 lines
kotlin
testing {
    suites {
        val test by getting(JvmTestSuite::class) {
            useJUnitJupiter()
        }
        val integrationTest by registering(JvmTestSuite::class) {
            useJUnitJupiter()
        }
    }
}

go deeper

for a junior

Know registering is for new suites and getting/named is for the existing test suite.

for a middle

Show both verbs in one block and explain the register-vs-named distinction and the check-wiring asymmetry.

for a senior

Relate the delegates to the underlying NamedDomainObjectContainer and the eager-API equivalents.

for a principal

Standardise the framework-selection block across modules so every project's test and extra suites share one declarative configuration style.

## One container, two access verbs The `testing { suites { } }` block is a `NamedDomainObjectContainer<JvmTestSuite>`. The plugin pre-populates it with **one** suite: `test`. So: - **Existing** suite (`test`) → fetch it: `val test by getting(JvmTestSuite::class) { ... }` or `suites.named("test") { ... }`. - **New** suite (`integrationTest`) → create it: `val integrationTest by registering(JvmTestSuite::class) { ... }` or `suites.register("integrationTest") { ... }`. ```kotlin testing { suites { // reconfigure the built-in suite val test by getting(JvmTestSuite::class) { useJUnitJupiter() } // declare a brand-new suite val integrationTest by registering(JvmTestSuite::class) { useJUnitJupiter() } } } ``` ## Why `getting` vs `registering` These are Kotlin DSL delegated-property helpers on `NamedDomainObjectContainer`: - `registering` = *register a new element lazily*, returns a provider, fails if the name already exists. - `getting` = *look up an existing element lazily*, fails if it doesn't exist. They mirror `tasks.register` vs `tasks.named`. Using the wrong verb gives a clear error ("cannot add ... already exists" or "unknown element"). ## What configuring `test` buys you The built-in `test` suite still benefits from the DSL: `useJUnitJupiter()` selects the framework and provisions the JUnit 5 dependency, replacing a separate `tasks.test { useJUnitPlatform() }` + manual dependency. So even projects with no extra suites use this block to pick their framework. ## The symmetry, and the one asymmetry After registration, `integrationTest` is structurally identical to `test`: same auto-derived source set, task, and configurations. The single asymmetry: `test` is wired into `check` automatically; `integrationTest` is not, so you add `tasks.named("check") { dependsOn(...) }`. ## Equivalent imperative API If you avoid the Kotlin delegates, the eager/named API is identical in effect: ```kotlin testing.suites.named("test", JvmTestSuite::class) { useJUnitJupiter() } testing.suites.register("integrationTest", JvmTestSuite::class) { useJUnitJupiter() } ```

  • What happens if you use `registering` on the name `test`?
    It fails — `registering` tries to create a new element, but `test` already exists in the container. Use `getting`/`named` to configure the pre-existing built-in suite.
  • Without the Kotlin delegates, what API configures the existing test suite?
    `testing.suites.named("test", JvmTestSuite::class) { useJUnitJupiter() }` — the `named` lookup mirrors `getting`.

saying these in an interview costs you the question

  • Claiming you must use `registering` for the built-in `test` suite — it already exists, so registering it errors.
  • Saying the built-in suite can't use the suites DSL — it does; that is how many projects pick their test framework.

context