This message was deleted.
# plugin-development
s
This message was deleted.
The way I do my tests is with a matrix outside my tests, configuring the test task with a specific toolchain (I personally use a matrix in my GitHub Actions workflow, invoking the same test task with a different toolchain and a system property for the Gradle version to test against; but you could create multiple test tasks instead, each with its own toolchain, and keep using parameterized tests for the Gradle version, ignoring incompatible associations. In any case, this requires you to compile your tests down to the lowest JDK version you intend to run them with.
t
thanks for the tip @Thomas Broyer šŸ‘Œ
v
That's not correct though. It is true that a convenient
withJavaVersion
or
withToolchain
is missing, but you can do it. Make the SUT build have a
gradle.properties
file where the property
org.gradle.java.home
is set to what the test should run with and it works as expected. I calculate the values for these by using
javaToolchains
extension to get the toolchains provisioned, then set system properties on the test task with the path, then read those system properties in the test to generate the appropriate
gradle.properties
. Works like a charm here.
t
Oh, good to know! Even keeping my matrix approach I could use that instead of running the tests themselves with the target JDK.
t
@Thomas Broyer Running it on GH Actions like you do negates use of the java toolchain right? (I'm guessing that you can't override the toolchain specified java version for running the tests using the GradleRunner by use of properties ...) @Vampire your version requires all the required JDKs be specified with the toolchain configuration right? I wanted my project to compile the plugin itself to run on JVM 8 or 11, but the tests themselves to be written using whatever is the latest JDK... that means that there would be JDK8 and JDK21 configured through the toolchain of the actual plugin project, but the tests should run with Gradle 8.5 using JDK21, 7.6.3 using JDK17 and so on for backwards compatibility checks. Developers won't necessarily have all of these installed ... do you think you can use
org.gradle.java.installations.auto-download=true
in the test specific gradle.properties file in some way to get all the required JDKs available for the tests?
t
See https://github.com/tbroyer/gradle-errorprone-plugin/blob/096ebddb2330d782f34717600743214b391c3634/.github/workflows/gradle.yaml#L87 and https://github.com/tbroyer/gradle-errorprone-plugin/blob/096ebddb2330d782f34717600743214b391c3634/build.gradle.kts#L87-L94 for an example of how I do it. I don't use toolchains to install the JDKs (fwiw, I even disabled auto-download locally in my
~/.gradle/gradle.properties
), only to run the test task with the appropriate JDK. I have no idea how/when Gradle will attempt to download them (and don't want to know)
t
oh that's nifty šŸ‘
… and combining that with @Vampire’s approach would make it even better. Thanks guys 😁
though ... how would we go about having a toolchain that's not configured for regular code, but in essence test resources?
t
@Vampire Do you have some sample code to get the "java home" for a given toolchain to pass as a system property to the tests?
v
Sure, I just was on mobile when I wrote the original message, one moment
Copy code
testing {
    suites {
        val functionalTest by registering(JvmTestSuite::class) {
            targets.configureEach {
                testTask {
                    val java17Home = javaToolchains
                        .launcherFor { languageVersion.set(JavaLanguageVersion.of(17)) }
                        .get()
                        .metadata
                        .installationPath
                        .asFile
                        .absolutePath
                    systemProperty("java17Home", java17Home)
                }
            }
        }
    }
}
and in the test code
Copy code
def 'test with Java 17'() {
   given:
      def java17Home = System.getProperty('java17Home')
      assert java17Home

   and:
      gradleProperties << """
         org.gradle.java.home = ${java17Home.replace($/\/$, $/\\/$)}
      """.stripIndent(true)

   when:
      runner
            .withArguments('help')
            .build()

   then:
      // ...
}
thank you 2
The top-level build will ensure the toolchain is provisioned and found, so
org.gradle.java.installations.auto-download=true
in the test-specific properties is not needed. It would even not be relevant, as you want to run the SUT test with a specific Java version I understood, not just use a specific toolchain within the SUT build. The latter would be no problem at all and would probably not have lead to this discussion. šŸ˜„
t
I hit a small snag combining Gradle 6.7 and jdk8 trying to put all of this together that might be relevant to this thread. Long story short you need to use
GradleRunner.withDebug(true)
, which causes TestKit to run without a daemon, or the daemon will terminate the build with
The newly created daemon process has a different context than expected.
. My java-home for jdk8 has symlinks to the actual content. I.e.
/path/to/java/zulu-8.72.0.17
has symlinks to
bin
,
jre
, etc, whereas the actual directories are in a subdirectory. I tried putting
org.gradle.daemon=false
in the properties file along with the java-home, but I couldn't get it to work consistently with Gradle 6.7. Other than that everything worked just as expected. Thanks for all the help guys! šŸ™‡ā€ā™‚ļø
v
Yeah such symlink-excesses are often cause of problems starting the demon as the used Java does not match the reported Java