From 36f6dd2514042fb0aa1dd8b8cad45fd15933268a Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Wed, 5 Aug 2026 10:35:32 -0400 Subject: [PATCH] Allow forked test tasks for source sets other than test Co-Authored-By: Claude Opus 5 (1M context) --- gradle/java_no_deps.gradle | 9 ++------- gradle/test-suites.gradle | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/gradle/java_no_deps.gradle b/gradle/java_no_deps.gradle index df5530e2a9c..d61f1dcd672 100644 --- a/gradle/java_no_deps.gradle +++ b/gradle/java_no_deps.gradle @@ -150,13 +150,8 @@ ext.testcontainersLimit = gradle.sharedServices.registerIfAbsent("testcontainers maxParallelUsages = project.findProperty("testcontainersMaxParallelUsages").toInteger() } -// Task for tests that want to run forked in their own separate JVM -tasks.register('forkedTest', Test) { - group = LifecycleBasePlugin.VERIFICATION_GROUP - useJUnitPlatform() - testClassesDirs = sourceSets.test.output.classesDirs - classpath = sourceSets.test.runtimeClasspath -} +// Every project gets a forked test task for its default 'test' source set. +addForkedTestTask('test') // testRuntimeActivation is registered in individual module build files after this convention is // applied, so tasks.named() won't work here — use a lazy hook that intercepts it on registration. diff --git a/gradle/test-suites.gradle b/gradle/test-suites.gradle index c93ceea3b8f..a1c81cd8c4f 100644 --- a/gradle/test-suites.gradle +++ b/gradle/test-suites.gradle @@ -77,3 +77,29 @@ ext.addTestSuiteForDir = { testSuiteName, dirName -> ext.addTestSuite = { testSuiteName -> ext.addTestSuiteForDir(testSuiteName, testSuiteName) } + +// Registers a task that runs the '*ForkedTest' classes of a source set, each in its own JVM. +// +// The task name ends in 'ForkedTest', which is what makes the test convention plugin restrict it to +// '**/*ForkedTest*', set forkEvery=1 and apply the shared forked-test concurrency limit. 'check', +// 'allTests' and 'allLatestDepTests' pick the task up automatically, because they match Test tasks +// by type rather than by name. +// +// Modules whose tests live in the default 'test' source set get 'forkedTest' registered for them by +// java_no_deps.gradle. Modules that use their own suites instead - for example to compile the same +// tests against several Scala versions - have no 'test' sources, so their forked tests never run +// unless they opt in: +// +// addTestSuite('baseTest') +// addForkedTestTask('baseTest') // registers 'baseTestForkedTest' +// +// Returns the TaskProvider so callers can configure the task further. +ext.addForkedTestTask = { String sourceSetName -> + def taskName = sourceSetName == 'test' ? 'forkedTest' : "${sourceSetName}ForkedTest" + return tasks.register(taskName, Test) { + group = LifecycleBasePlugin.VERIFICATION_GROUP + useJUnitPlatform() + testClassesDirs = sourceSets[sourceSetName].output.classesDirs + classpath = sourceSets[sourceSetName].runtimeClasspath + } +}