How do I add a new sourceset to Gradle?
Solution 1:
Update for 2021:
A lot has changed in 8ish years. Gradle continues to be a great tool. Now there's a whole section in the docs dedicated to configuring Integration Tests. I recommend you read the docs now.
Original Answer:
This took me a while to figure out and the online resources weren't great. So I wanted to document my solution.
This is a simple gradle build script that has an intTest source set in addition to the main and test source sets:
apply plugin: "java"
sourceSets {
// Note that just declaring this sourceset creates two configurations.
intTest {
java {
compileClasspath += main.output
runtimeClasspath += main.output
}
}
}
configurations {
intTestCompile.extendsFrom testCompile
intTestRuntime.extendsFrom testRuntime
}
task intTest(type:Test){
description = "Run integration tests (located in src/intTest/...)."
testClassesDir = project.sourceSets.intTest.output.classesDir
classpath = project.sourceSets.intTest.runtimeClasspath
}
Solution 2:
Here is how I achieved this without using configurations{ }
.
apply plugin: 'java'
sourceCompatibility = JavaVersion.VERSION_1_6
sourceSets {
integrationTest {
java {
srcDir 'src/integrationtest/java'
}
resources {
srcDir 'src/integrationtest/resources'
}
compileClasspath += sourceSets.main.runtimeClasspath
}
}
task integrationTest(type: Test) {
description = "Runs Integration Tests"
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath += sourceSets.integrationTest.runtimeClasspath
}
Tested using: Gradle 1.4 and Gradle 1.6
Solution 3:
This was once written for Gradle 2.x / 3.x in 2016 and is far outdated!! Please have a look at the documented solutions in Gradle 4 and up
To sum up both old answers (get best and minimum viable of both worlds):
some warm words first:
-
first, we need to define the
sourceSet
:sourceSets { integrationTest }
-
next we expand the
sourceSet
fromtest
, therefor we use thetest.runtimeClasspath
(which includes all dependenciess fromtest
ANDtest
itself) as classpath for the derivedsourceSet
:sourceSets { integrationTest { compileClasspath += sourceSets.test.runtimeClasspath runtimeClasspath += sourceSets.test.runtimeClasspath // ***) } }
-
note) somehow this redeclaration / extend for
sourceSets.integrationTest.runtimeClasspath
is needed, but should be irrelevant sinceruntimeClasspath
always expandsoutput + runtimeSourceSet
, don't get it
-
note) somehow this redeclaration / extend for
-
we define a dedicated task for just running integration tests:
task integrationTest(type: Test) { }
-
Configure the
integrationTest
test classes and classpaths use. The defaults from thejava
plugin use thetest
sourceSet
task integrationTest(type: Test) { testClassesDir = sourceSets.integrationTest.output.classesDir classpath = sourceSets.integrationTest.runtimeClasspath }
-
(optional) auto run after test
integrationTest.dependsOn test
-
(optional) add dependency from
check
(so it always runs whenbuild
orcheck
are executed)tasks.check.dependsOn(tasks.integrationTest)
-
(optional) add java,resources to the
sourceSet
to support auto-detection and create these "partials" in your IDE. i.e. IntelliJ IDEA will auto createsourceSet
directories java and resources for each set if it doesn't exist:sourceSets { integrationTest { java resources } }
tl;dr
apply plugin: 'java'
// apply the runtimeClasspath from "test" sourceSet to the new one
// to include any needed assets: test, main, test-dependencies and main-dependencies
sourceSets {
integrationTest {
// not necessary but nice for IDEa's
java
resources
compileClasspath += sourceSets.test.runtimeClasspath
// somehow this redeclaration is needed, but should be irrelevant
// since runtimeClasspath always expands compileClasspath
runtimeClasspath += sourceSets.test.runtimeClasspath
}
}
// define custom test task for running integration tests
task integrationTest(type: Test) {
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
}
tasks.integrationTest.dependsOn(tasks.test)
referring to:
- gradle java chapter 45.7.1. Source set properties
- gradle java chapter 45.7.3. Some source set examples
Unfortunatly, the example code on github.com/gradle/gradle/subprojects/docs/src/samples/java/customizedLayout/build.gradle or …/gradle/…/withIntegrationTests/build.gradle seems not to handle this or has a different / more complex / for me no clearer solution anyway!
Solution 4:
The nebula-facet plugin eliminates the boilerplate:
apply plugin: 'nebula.facet'
facets {
integrationTest {
parentSourceSet = 'test'
}
}
For integration tests specifically, even this is done for you, just apply:
apply plugin: 'nebula.integtest'
The Gradle plugin portal links for each are:
- nebula.facet
- nebula.integtest