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:

  1. first, we need to define the sourceSet:

    sourceSets {
        integrationTest
    }
    
  2. next we expand the sourceSet from test, therefor we use the test.runtimeClasspath (which includes all dependenciess from test AND test itself) as classpath for the derived sourceSet:

    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 since runtimeClasspath always expands output + runtimeSourceSet, don't get it
  3. we define a dedicated task for just running integration tests:

    task integrationTest(type: Test) {
    }
    
  4. Configure the integrationTest test classes and classpaths use. The defaults from the java plugin use the test sourceSet

    task integrationTest(type: Test) {
        testClassesDir = sourceSets.integrationTest.output.classesDir
        classpath = sourceSets.integrationTest.runtimeClasspath
    }
    
  5. (optional) auto run after test

    integrationTest.dependsOn test
    
  6. (optional) add dependency from check (so it always runs when build or check are executed)

    tasks.check.dependsOn(tasks.integrationTest)
    
  7. (optional) add java,resources to the sourceSet to support auto-detection and create these "partials" in your IDE. i.e. IntelliJ IDEA will auto create sourceSet 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:

  1. nebula.facet
  2. nebula.integtest