Multi-project testCompile dependencies cause problems with Eclipse and IDEA build paths

I have a multi-project build where ProjectB depends on ProjectA and the test code in ProjectB also needs test code in project A. This is what ProjectA build.gradle looks like:

dependencies {
 // some compile dependencies here
   testCompile group: 'org.testng', name: 'testng', version: '6.5.2'
}
  test {
 useTestNG()
}

And this is what ProjectB build.gradle currently looks like:

dependencies {
 compile project(':ProjectA')
 // more compile dependencies
   testCompile group: 'org.testng', name: 'testng', version: '6.5.2'
 testCompile project(':ProjectA').sourceSets.test.output
}
  test {
 useTestNG()
}

This works great when running “gradle test”, but it doesn’t work so well with “gradle idea” and “gradle eclipse”.

The configuration files for IDEA include the reference in module ProjectB to ProjectA, in “Compile” scope and also a references to directories “build/classes/test” and “build/resources/test” in ProjectA, in “Test” scope. This is not a big deal, because IDEA lets me build the project despite the missing “build/resources/test” directory. The only annoyance is the fact that some classes will be available for import twice and if I’ve moved some of them from one package to another I have to be careful to import the ones provided by the “Compile” scope module reference.

However, the real problem is in Eclipse. It also has the duplicate dependencies: there’s a build path entry for ProjectA under “Projects” and two build path entries, one for “build/classes/test” in ProjectA and one for “build/resources/test” in ProjectA, under “Libraries”. The problem is that Eclipse won’t let me build ProjectB unless “build/resources/test” exists. ProjectA currently doesn’t have resources. I could add the “src/test/resources” by hand and see whether Gradle creates “build/resources/test” from that, but it’s cumbersome and breaks what I tell people in my project: 1) download source from Git, then 2) run “gradle eclipse” or “gradle idea” and you’re ready to go!

Here’s the “gradle -v” output on my machine:

------------------------------------------------------------
Gradle 1.0-milestone-8a
------------------------------------------------------------
  Gradle build time: Monday, February 20, 2012 4:00:18 PM UTC
Groovy: 1.8.4
Ant: Apache Ant(TM) version 1.8.2 compiled on December 20 2010
Ivy: 2.2.0
JVM: 1.6.0_24 (Sun Microsystems Inc. 19.1-b02)
OS: Windows XP 5.1 x86

JVM version and OS will vary (we have automated builds on Linux machines), but JVM version is guaranteed not to go below 6.

Is there any way to have ProjectB test code have access to ProjectA test code without messing up Eclipse and IDEA files? Am I doing something wrong?

To solve the problem with the not existing resource dir, you can use ‘sourceSets.test.output.classesDir’ or filter ‘sourceSets.test.output’ for existing directories. (Something like ‘sourceSets.test.output.findAll { it.exists() }’ should do the job.)

For best IDE experience, you might have to move the reused test code into its own project. As soon as you are adding external classes directories, you are depending on code that doesn’t get compiled by the IDE and can easily go stale. I guess you could solve the problem to some extent by configuring the IDE plugins to add the IDE’s output directories instead of the Gradle build’s output directories. (You could also configure the IDE plugins to use the same output directories as the Gradle build, but that has its own set of problems, and I don’t recommend it.) Still, the IDEs might not fully understand when they have to recompile that code.