TestKit DSL - nebula-plugins/nebula-test GitHub Wiki
The TestKit DSL provides a new abstraction over Gradle TestKit which is usable in Java, Groovy, and Kotlin, and can be used with any unit testing framework. It assists in setting up a sample project, with an API that makes the structure of the project easily understandable to the reader of the test. This implementation is in an MVP state, with more functionality planned to cover common use cases.
Project Builder
The project builder assists with authoring the files of a Gradle project in a temporary directory. The result of the project builder is a TestProjectRunner, which will be covered in the next section.
Example (Kotlin + JUnit Jupiter):
internal class KotlinDslTest {
@TempDir
lateinit var testProjectDir: File
fun `test single project build with sources`() {
val runner = testProject(testProjectDir) {
rootProject {
plugins {
java()
}
src {
main {
java("Main.java") {
// language=java
"""
public class Main {
public static void main(String[] args) {
}
}
"""
}
}
}
}
}
}
}
Project Runner
The TestProjectRunner allows you to invoke the Gradle TestKit runner, with options, on your project. This is just a very thin wrapper around the TestKit GradleRunner that provides more ideomatic syntax for Groovy and Kotlin and handles setting the correct project directory for you. All options of the TestKit GradleRunner are exposed through the invocation DSL. The result is a TestKit BuildResult.
Example:
val result = runner.run("build") {
forwardOutput()
withGradleVersion("9.0.0")
}
Assertions
This library also provides custom AssertJ assertions for the BuildResult. These can be used in Java, Kotlin, or Groovy, as long as you are using AssertJ.
Example:
assertThat(result)
.hasNoDeprecationWarnings()
.hasNoMutableStateWarnings()
assertThat(result).task(":compileJava").hasOutcome(TaskOutcome.SUCCESS)
assertThat(result).task(":build").hasOutcome(TaskOutcome.SUCCESS)
Temporary Project Directory
Unlike the Spock helpers, the TestKit DSL does not manage the temporary project directory. This is outside the abstraction so that it can be delegated to the helper for whichever test framework is being used. If you would like the project directory to be in the project build directory, and not cleaned up after the test run, this can be done using your test framework. For example, Junit5 has the TempDirFactory interface that you can use with a meta-annotation to achieve this effect. Example.
More Examples
Example (Groovy + Spock):
class GroovyDslSpockTest extends Specification {
@TempDir
File testProjectDir
@Unroll
void "test groovy DSL with spock"() {
setup:
final var runner = GroovyTestProjectBuilder.testProject(testProjectDir) {
settings {
plugins {
id("org.gradle.toolchains.foojay-resolver-convention").version("0.10.0")
}
}
rootProject {
plugins {
java()
}
javaToolchain(javaVersion)
src {
main {
java("Main.java") {
// language=java
"""
public class Main {
public static void main(String[] args) {
}
}
"""
}
}
}
}
}
when:
final var result = runner.run(["build"]) {
withGradleVersion(gradle.version)
forwardOutput()
}
then:
assertThat(result)
.hasNoDeprecationWarnings()
.hasNoMutableStateWarnings()
assertThat(result).task(":compileJava").hasOutcome(TaskOutcome.SUCCESS)
assertThat(result).task(":build").hasOutcome(TaskOutcome.SUCCESS)
where:
javaVersion | gradle
11 | SupportedGradleVersion.MIN
17 | SupportedGradleVersion.MAX
}
}