Problem running test tasks in parallel in a multiproject build


(rajesh.eq) #1

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.


(Benjamin Muschko) #2

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.


(rajesh.eq) #3

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])


(rajesh.eq) #4

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])


(rajesh.eq) #5

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

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


(Benjamin Muschko) #6

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.


(rajesh.eq) #7

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


(rajesh.eq) #8

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

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