Problem running test tasks in parallel in a multiproject build

Using a multiproject build I am trying to run two test tasks in parallel. The test tasks are present in different sub-projects. But the test task fails with the initialization error:

java.lang.Exception: No runnable methods

at org.junit.runners.BlockJUnit4ClassRunner.validateInstanceMethods(BlockJUnit4ClassRunner.java:169)

at org.junit.runners.BlockJUnit4ClassRunner.collectInitializationErrors(BlockJUnit4ClassRunner.java:104)

at org.junit.runners.ParentRunner.validate(ParentRunner.java:355)

at org.junit.runners.ParentRunner.(ParentRunner.java:76)

at org.junit.runners.BlockJUnit4ClassRunner.(BlockJUnit4ClassRunner.java:57)

at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)

at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)

at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)

at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)

at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:26)

at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:74)

at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:47)

at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:69)

at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:49)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:597)

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)

I am able to run the same test if I move the test to parent project. All projects tasks and properties are defined in the root project. Can’t understand why The test tasks fails with initialization error.

One of your test classes does not add the required @Test annotations. You will need to have at least one method annotated otherwise you’ll see this message.

No, all the classes have the @Test annotations. Here is the parent build.gradle script

apply plugin: ‘java’ apply plugin: ‘eclipse’

sourceCompatibility = 1.5 version = ‘1.0’ jar {

manifest {

attributes ‘Implementation-Title’: ‘Gradle Quickstart’, ‘Implementation-Version’: version

} }

repositories {

mavenCentral() }

dependencies {

compile group: ‘commons-collections’, name: ‘commons-collections’, version: ‘3.2’

testCompile group: ‘junit’, name: ‘junit’, version: ‘4.+’ }

project(’:u’){

sourceSets

{

unitTest{

java

{

srcDir “$rootProject.projectDir/src/unit/java”

}

compileClasspath += test.compileClasspath

}

}

task unitTest(type: Test){

testClassesDir file("$rootProject.buildDir/classes/unitTest")

classpath = sourceSets.unitTest.output

include “org/gradle/PersonTest2.class”

outputs.upToDateWhen { false }

testResultsDir file("$rootProject.buildDir/results/u")

binResultsDir file("$rootProject.buildDir/bin/u")

testReportDir file("$rootProject.buildDir/reports/u")

workingDir file("$rootProject.buildDir")

ignoreFailures true

scanForTestClasses false

doLast{

// To see whether tests run in parallel

for(int i=0; i<10;i++){

sleep(1500)

println “from u $i”

}

}

} }

project(’:e’){

sourceSets

{

e2eTest{

java

{

srcDir “$rootProject.projectDir/src/e2e/java”

}

compileClasspath += test.compileClasspath

}

}

task e2eTest(type: Test){

testClassesDir file("$rootProject.buildDir/classes/e2eTest")

classpath = sourceSets.e2eTest.output

classpath.each{println it}

include “org/gradle/PersonTest1.class”

outputs.upToDateWhen { false }

workingDir file("$rootProject.buildDir")

testResultsDir file("$rootProject.buildDir/results/e")

binResultsDir file("$rootProject.buildDir/bin/e")

testReportDir file("$rootProject.buildDir/reports/e")

workingDir file("$rootProject.buildDir")

scanForTestClasses false

ignoreFailures true

doLast{

for(int i=0; i<10;i++){

sleep(1000)

println “from e $i”

}

} }}

task x(dependsOn: [’:u:unitTest’, ‘:e:e2eTest’, test])

No, all the Test has @Test annotation. Here is the parent build.gradle I am playing with

apply plugin: ‘java’ apply plugin: ‘eclipse’

sourceCompatibility = 1.5 version = ‘1.0’ jar {

manifest {

attributes ‘Implementation-Title’: ‘Gradle Quickstart’, ‘Implementation-Version’: version

} }

repositories {

mavenCentral() }

dependencies {

compile group: ‘commons-collections’, name: ‘commons-collections’, version: ‘3.2’

testCompile group: ‘junit’, name: ‘junit’, version: ‘4.+’ }

project(’:u’){

sourceSets

{

unitTest{

java

{

srcDir “$rootProject.projectDir/src/unit/java”

}

compileClasspath += test.compileClasspath

}

}

task unitTest(type: Test){

testClassesDir file("$rootProject.buildDir/classes/unitTest")

classpath = sourceSets.unitTest.output

include “org/gradle/PersonTest2.class”

outputs.upToDateWhen { false }

testResultsDir file("$rootProject.buildDir/results/u")

binResultsDir file("$rootProject.buildDir/bin/u")

testReportDir file("$rootProject.buildDir/reports/u")

workingDir file("$rootProject.buildDir")

ignoreFailures true

scanForTestClasses false

doLast{

// To see whether tests run in parallel

for(int i=0; i<10;i++){

sleep(1500)

println “from u $i”

}

}

} }

project(’:e’){

sourceSets

{

e2eTest{

java

{

srcDir “$rootProject.projectDir/src/e2e/java”

}

compileClasspath += test.compileClasspath

}

}

task e2eTest(type: Test){

testClassesDir file("$rootProject.buildDir/classes/e2eTest")

classpath = sourceSets.e2eTest.output

classpath.each{println it}

include “org/gradle/PersonTest1.class”

outputs.upToDateWhen { false }

workingDir file("$rootProject.buildDir")

testResultsDir file("$rootProject.buildDir/results/e")

binResultsDir file("$rootProject.buildDir/bin/e")

testReportDir file("$rootProject.buildDir/reports/e")

workingDir file("$rootProject.buildDir")

scanForTestClasses false

ignoreFailures true

doLast{

for(int i=0; i<10;i++){

sleep(1000)

println “from e $i”

}

} }}

task x(dependsOn: [’:u:unitTest’, ‘:e:e2eTest’, test])

No, I have checked all have @Test annotation. I have added my build.gradle here

https://gist.github.com/anonymous/7829021

Then there must be something wrong with your SourceSet configuration. Is there a reason for setting up a SourceSet for unit tests? The Java plugin provides you with one out-of-the-box. You will just need to reconfigure it.

Thanks for your reply Benjamin. My objective is to run two test tasks in parallel. Say for e.g. I want to run unit and integration test in parallel. Hence I am trying to convert it into a multi-module project.

I understand with in test task I can run in parallel mode. But it is not desired.

In this simplified build script, where I moved the sourceSet configuration back to parent project, I am getting the same initialization error.

https://gist.github.com/anonymous/7869815

The classpath was not configured correctly which was creating the problem. The full build script is here

https://gist.github.com/anonymous/7870525