Separate execution for Java Unit and Integration tests

Hi,

I have the following configuration in my gradle build related with unit and integration tests (I’m using JavaPlugin):

sourceSets {
  test {
    java.srcDir 'src/test/unit/java'
  }
  integration {
    java.srcDir 'src/test/integration/java'
    resources.srcDir 'src/test/resources'
    compileClasspath += main.output + test.output
    runtimeClasspath += main.output + test.output
  }
}

configurations {
  integrationCompile.extendsFrom testCompile
  integrationRuntime.extendsFrom testRuntime
}

task integration(type: Test, description: 'Runs the integration tests.', group: 'Verification') {
  testClassesDir = sourceSets.integration.output.classesDir
  classpath = sourceSets.integration.runtimeClasspath
}

When I run gradle integration, only the test classes in the integration java.srcDir SourceSet are executed, but when I run gradle test all tests classes are executed, the ones from test and integration SourceSet’s.
There is a way to run this tests separated, so gradle test execute tests only from test SourceSet and gradle integration execute tests from integration SourceSet?

Thanks!

Are you using an IDE like IntelliJ by any chance? It’s possible that your IDE is compiling both integration and unit tests to the same output directory which is causing Gradle to run all your tests when executing the test task.

@mark_vieira Yes, I’m using IntelliJ and you are correct, I executed gradle clean followed by a gradle test in Terminal and only classes in the test was executed.

Do you know how I can avoid this behavior in this IDE?

Thanks!

The IDE is trying to be smart by syncing up its output directory with the one Gradle is using. However, it’s not smart enough to support more than two source sets (main and test). You’ll want to change the output directory in IntelliJ to somewhere other than where Gradle is compiling two, that way they won’t clash. If you use the ‘idea’ plugin you can run the ‘idea’ task to generate IntelliJ metadata rather than using the built-in Gradle import. By default this will use the regular ‘out’ directory for compiled output.

@mark_vieira Just make sure that I understood you correctly, what I need to do is:
say that my gradle is building my project in ‘PROJECT_ROOT/build’ and so IDEA. I will need to change the IDEA to build in somewhere else, say ‘PROJECT_ROOT/build-idea’? Is that correct?

And taking the opportunity, if I’ve understand you correctly, do know if this change have any impact on some behavior or feature of the IDEA itself? Something like code assist or anything like?

Thanks for the help!

one remark about your build script:

test {
    java.srcDir 'src/test/unit/java'
}

adds a source directory to the default directory (src/test/java). instead you should use

test {
    java.srcDirs = ['src/test/unit/java']
}

same problem occurs in your integration source set configuration.

Does configuring the srcDirs fix the issue for you?

@Rene I’ve changed my configuration as you suggested and the problem with IntelliJ IDEA persist. As soon I make (CRTL/COMMAND+F9) the project in IDEA the classes from integration tests are copied to build/classes/test, the same target of unit tests, and after that if a I run gradle test all tests are executed.
To improve my knowledge on gradle, what is the impact of your suggestion, this is the best/recommended way to declare SourceSets?

And BTW, the suggestion of @mark_vieira do solve the problem, as long the IDEA build the classes in other place than gradle they don’t clash and everything works well.

Thanks for help guys.

By default the Java plugin looks for test src in ‘src/test/java’. Using your original method you are adding an additional source directory. So Gradle will now look in both directories. If that other directory doesn’t exist, then you really won’t see any difference.

1 Like

Hi, For me this was the solution:

in build.gradle

task unitTest(type: Test, description: ‘Runs the unit tests.’, group: ‘Verification’) {
useJUnit{
includeCategories ‘com.my.package.MyCategory’
}
}

in test code:

@Category({MyCategory.class})
public class MyTests {
}