问题
I want to add integration tests to my Gradle build (Version 1.0). They should run separately from my normal tests because they require a webapp to be deployed to localhost (they test that webapp). The tests should be able to use classes defined in my main source set. How do I make this happen?
回答1:
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
}
回答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
回答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!
回答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
回答5:
If you're using
- Gradle 5.x, have a look at Documentation Section "Testing Java > Configuring integration tests
Example 14 and 15 for details (both for Groovy and Kotlin DSL, either which one you prefer)
- alt: "current" Gradle doc link at 2, but might defer in future, you should have a look at if examples changes)
- for Gradle 4 have a look at ancient version 3 which is close near to what @Spina posted in 2012
To get IntelliJ to recognize custom sourceset as test sources root:
plugin {
idea
}
idea {
module {
testSourceDirs = testSourceDirs + sourceSets["intTest"].allJava.srcDirs
testResourceDirs = testResourceDirs + sourceSets["intTest"].resources.srcDirs
}
}
回答6:
Here's what works for me as of Gradle 4.0.
sourceSets {
integrationTest {
compileClasspath += sourceSets.test.compileClasspath
runtimeClasspath += sourceSets.test.runtimeClasspath
}
}
task integrationTest(type: Test) {
description = "Runs the integration tests."
group = 'verification'
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
}
As of version 4.0, Gradle now uses separate classes directories for each language in a source set. So if your build script uses sourceSets.integrationTest.output.classesDir
, you'll see the following deprecation warning.
Gradle now uses separate output directories for each JVM language, but this build assumes a single directory for all classes from a source set. This behaviour has been deprecated and is scheduled to be removed in Gradle 5.0
To get rid of this warning, just switch to sourceSets.integrationTest.output.classesDirs
instead. For more information, see the Gradle 4.0 release notes.
来源:https://stackoverflow.com/questions/11581419/how-do-i-add-a-new-sourceset-to-gradle