Search

Dark theme | Light theme

November 21, 2022

Gradle Goodness: Set Test Framework Version Using Version Catalog With JVM Test Suite Plugin

Since Gradle 7.3 we can use the JVM Test Suite plugin to define in a declarative way tests for our build. For example adding integration tests with a new source set and dependencies becomes easier with this plugin. The plugin is automatically part of the Java plugin so we don't have to define it explicitly in our build. Configuring the default test task can also be done using the syntax of the JVM TestSuite plugin. We can use several methods from the JvmTestSuite class in our configuration. For example if we want to use Spock as testing framework we can simply add the method useSpock in our build script. Or if we want to use the JUnit 5 Jupiter engine we can use useJUnitJupiter. These methods will add dependencies in the testImplementation configuration. There is a default version for the dependencies if we use the method without arguments. But we can also define the version as String argument for these methods. The version catalog for our project is the place to store version for our dependencies, so it would be nice if we could use the version defined in our version catalog as argument for the use<TestFramework> methods. We can reference the version very simple by using libs.versions.<version-key>. This will return the value we defined as version in our version catalog.

In the following example build script we want to use JUnit Jupiter version 5.9.1, instead of the default version of 5.8.2. We use the version as it is defined in our version catalog file libs.versions.toml:

// File: build.gradle.kts
plugins {
    java // The Java plugin also includes the JVM Test Suite plugin.
}

// We need to define a repository so JUnit dependencies can be downloaded.
repositories {
    mavenCentral()
}

testing {
    suites {
        // Using JVM Test Suite feature to configure our test task.
        val test by getting(JvmTestSuite::class) {
            // For JUnit 5 we need to enable JUnit Jupiter.
            // If we don't specify a version the default
            // version is used, which is 5.8.2 with Gradle 7.6.
            // We can use a version as String as argument, but it is even
            // better to refer to a version from the version catalog,
            // so all versions for our dependencies are at the
            // single location of the version catalog.
            // We define the version in libs.versions.toml.
            useJUnitJupiter(libs.versions.junit)
        }
    }
}

In the file gradle/libs.versions.toml we have the following definition:

# gradle/libs.versions.toml
[versions]
junit = "5.9.1"    

When we check our dependencies we see the correct dependencies for JUnit:

$ gradle dependencies --configuration testCompileClasspath
...
------------------------------------------------------------
Root project 'testsuite'
------------------------------------------------------------

testCompileClasspath - Compile classpath for source set 'test'.
\--- org.junit.jupiter:junit-jupiter:5.9.1
     +--- org.junit:junit-bom:5.9.1
     |    +--- org.junit.jupiter:junit-jupiter:5.9.1 (c)
     |    +--- org.junit.jupiter:junit-jupiter-api:5.9.1 (c)
     |    +--- org.junit.jupiter:junit-jupiter-params:5.9.1 (c)
     |    \--- org.junit.platform:junit-platform-commons:1.9.1 (c)
     +--- org.junit.jupiter:junit-jupiter-api:5.9.1
     |    +--- org.junit:junit-bom:5.9.1 (*)
     |    +--- org.opentest4j:opentest4j:1.2.0
     |    +--- org.junit.platform:junit-platform-commons:1.9.1
     |    |    +--- org.junit:junit-bom:5.9.1 (*)
     |    |    \--- org.apiguardian:apiguardian-api:1.1.2
     |    \--- org.apiguardian:apiguardian-api:1.1.2
     \--- org.junit.jupiter:junit-jupiter-params:5.9.1
          +--- org.junit:junit-bom:5.9.1 (*)
          +--- org.junit.jupiter:junit-jupiter-api:5.9.1 (*)
          \--- org.apiguardian:apiguardian-api:1.1.2

(c) - dependency constraint
(*) - dependencies omitted (listed previously)
...

Written with Gradle 7.6.