Multi-module project and integration testing (junit)

I’m working on migrating a multi-module Maven build (100+ modules) where some of the modules just contain integration tests executed via JUnit. These test modules have dependencies on multiple modules, often transitively. The tests use Spring so need a config directory, from each of the modules on which it depends, to be on the classpath when tests are executed. How can I go about achieving that?

I am able to add the config directory for modules I know will be depended upon:

root build.gradle (module build.gradle files just contain compile and runtime dependencies)

subprojects {
    configurations {
        testCompile.extendsFrom runtime
    }
    
    configurations {
        bootstrapConfig {
            description = 'Bootstrap config required by all runnable processes'
        }
    }
    dependencies {
        bootstrapConfig files("$rootDir/bootstrap/src/main/config")
    }
    
    sourceSets.test.runtimeClasspath += configurations.bootstrapConfig
}

My question is how do I get the /src/main/config directory for each module on which there is a dependency (including transitive dependencies) on to the test classpath?

I tried writing a method that would iterate resolved dependencies to build the classpath but hit problems with messages like this:

Changed dependencies of configuration ‘actionservice:compile’ after it has been included in dependency resolution. This behaviour has been deprecated and is scheduled to be removed in Gradle 3.0.
Changed dependencies of parent of configuration ‘actionservice:runtime’ after it has been resolved. This behaviour has been deprecated and is scheduled to be removed in Gradle 3.0

subprojects {
    def buildTestClasspath = { proj ->
            def FileCollection classpath = files("$rootDir/bootstrap/src/test/config")
            proj.configurations.runtime.resolvedConfiguration*.resolvedArtifacts.each {
                // blah, blah blah
            }
    }
    sourceSets.test.runtimeClasspath += configurations.buildTestClasspath(project)
}

All help appreciated!

I think you need something like following code in your root project’s build.gradle file.

def configDirs = []
subprojects.each { p ->
    configDirs.add(p.getProjectDir().getPath() + "/config/dir/in/project")
    println p.getProjectDir().getPath() + "/config/dir/in/project"
}

subprojects {
    dependencies {
        configDirs.each { d ->
            testCompile files(d)
        }
    }
}

This snippet walks through all subprojects get’s theirs directories and places them as testCompile dependency to those projects. So each subproject will test-depend on all other subprojects in your build. Of course this is just a hint. You can add some logic into this script like File.exists check or exclude dependency on project itself.

Btw. to quickly check out what’s on classpath while testing your project by gradle you can create a test that will print classpath on console.

@Test
public void printOutClasspathTest() {
	System.out.println("=== test's classpath ===");
	ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
	URL[] systemUrls = ((URLClassLoader)systemClassLoader).getURLs();
	for(URL url: systemUrls){
		System.out.println(url.getFile());
	}
}
// Run this with: gradle test --info