Junit tests failing to find test resources, despite showing them in the runtimeClasspath


(Petula Guimaraes) #1

Hello, I have a multi-project build in Gradle. This is the folder structure:

rootproject ---- subprojectA -------src ----------packages ----------xml ----------tests ---------------packages ---- subprojectB (…)

For some subprojects the tests read files from /xml subfolders and they execute fine via eclipse.

However, via Gradle command line they fail to find /xml folder and subfolders. A sample message is:

09:26:34.497 [DEBUG] [TestEventLogger]
       Caused by:
09:26:34.497 [DEBUG] [TestEventLogger]
       com.msdw.ird.refdata.storage.ReferenceDataStorageServiceException: ReferenceData directory does not exist xml/referencedata

Funny thing is that I get those files in the classpath once I print it:

(...)
09:24:16.112 [QUIET] [system.out] classpath damn file: "/a/nyn166f2/vol/nyn166f2v4/u_t1395154848/petulag/ird.trend/ird/trend/alternative/build/refdata/resources/main/xml/soap/ReloadReferenceData.xml"
09:24:16.112 [QUIET] [system.out] classpath damn file: "/a/nyn166f2/vol/nyn166f2v4/u_t1395154848/petulag/ird.trend/ird/trend/alternative/build/refdata/resources/main/xml/tests/stsRegionEnvSpecifics.xml"
(...)

I’ve been trying many different things, assuming I might have a classpath issue.

Here is how my build.gradle for the subproject looks like as of today:

sourceSets {
           main {
           java.srcDirs = [ 'src/packages']
           resources.srcDirs = [ 'src/packages', 'src' ]
             compileClasspath = compileClasspath + configurations.legacy
             runtimeClasspath = project.sourceSets.main.compileClasspath +
                         project.sourceSets.test.compileClasspath +
                         fileTree("${buildDir}/resources/test") + fileTree("${buildDir}/resources/main") +
                         project.sourceSets.test.output + project.sourceSets.main.output
        }
          test {
                java.srcDirs = [
'src/tests/packages']
                resources.srcDirs = [ 'src'
]
                  runtimeClasspath = project.sourceSets.main.compileClasspath +
                         project.sourceSets.test.compileClasspath +
                         fileTree("${buildDir}/resources/test") + fileTree("${buildDir}/resources/main") +
                         project.sourceSets.test.output + project.sourceSets.main.output
                       }
}
  dependencies {
          compile project(':proj1)
        compile project(':proj2)
        compile project(':proj3)
          compile group:'proprietarylib', name: 'hsqldb', version: 'v1', configuration: 'runtime'
}
  test.doFirst {
         println "Test classpath is:- "
         sourceSets.test.runtimeClasspath.getFiles().each { file ->
                 println "classpath damn file: \"" + file + "\""
         }
}
  test {
        systemProperty "testDataDir", "${buildDir}/resources/test"
        include "**/*Test*.class"
          systemProperty "main.tests.data.build.dir", "${buildDir}/resources/test"
}

Any ideas on what I am missing? Could it be some “weird” classloading issue?

Thanks! Petula


(Petula Guimaraes) #2

Btw, I noticed i posted the code strangely, so here it is the root project file:

buildscript {
    def msde_gradle_path = '//myDyrectory/PROJ/gradle/2014.04.17-1/common'
    apply from: "${int_gradle_path}/etc/buildinfra/buildscript.gradle", to: buildscript
}
  // Apply our internal/gradle plugins
apply plugin: 'int-multi-project'
apply plugin: 'int-default-versions'
  msbundleSets {
    ext.ourjavaBundle = 'ourJava:parts:2013.09.02'
}
  subprojects {
    apply plugin: 'int-ourjavaresolvers'
      repositories {
        add(ourjavaresolvers.afsDist())
        add(ourjavaresolvers.msjavaIvyRepDist())
        add(ourjavaresolvers.multiProjectAFSDist())
      }
      ext.ver = [
        'junit': '4.11.0.1ms'
    ]
          configurations {
                legacy
        }
  }

And the subproject file

sourceSets {
           main {
           java.srcDirs = [ 'src/packages']
           resources.srcDirs = [ 'src/packages', 'src' ]
             compileClasspath = compileClasspath + configurations.legacy
             runtimeClasspath = project.sourceSets.main.compileClasspath +
                         project.sourceSets.test.compileClasspath +
                         fileTree("${buildDir}/resources/test") + fileTree("${buildDir}/resources/main") +
                         project.sourceSets.test.output + project.sourceSets.main.output
        }
          test {
                java.srcDirs = [
'src/tests/packages']
                resources.srcDirs = [ 'src'
]
                  runtimeClasspath = project.sourceSets.main.compileClasspath +
                         project.sourceSets.test.compileClasspath +
                         fileTree("${buildDir}/resources/test") + fileTree("${buildDir}/resources/main") +
                         project.sourceSets.test.output + project.sourceSets.main.output
                       }
}
  dependencies {
          compile project(':'proj1')
        compile project(':proj2')
        compile project(':proj3')
          compile group:'proprietarylib', name: 'hsqldb', version: '1.8.0.8', configuration: 'runtime'
}
  test.doFirst {
         println "Test classpath is:- "
         sourceSets.test.runtimeClasspath.getFiles().each { file ->
                 println "classpath damn file: \"" + file + "\""
         }
}
  test {
        systemProperty "testDataDir", "${buildDir}/resources/test"
        include "**/*Test*.class"
          systemProperty "main.tests.data.build.dir", "${buildDir}/resources/test"
}

(Petula Guimaraes) #3

Another attempt to post my gradle file correctly

sourceSets {
         main {
           java.srcDirs = [ 'src/packages']
           resources.srcDirs = [ 'src/packages', 'src' ]
           compileClasspath = compileClasspath + configurations.legacy
           runtimeClasspath = project.sourceSets.main.compileClasspath +
                         project.sourceSets.test.compileClasspath +
                         fileTree("${buildDir}/resources/test") + fileTree("${buildDir}/resources/main") +
                         project.sourceSets.test.output + project.sourceSets.main.output
        }
        test {
                java.srcDirs = [
'src/tests/packages']
                resources.srcDirs = [ 'src'
]
                runtimeClasspath = project.sourceSets.main.compileClasspath +
                         project.sourceSets.test.compileClasspath +
                         fileTree("${buildDir}/resources/test") + fileTree("${buildDir}/resources/main") +
                         project.sourceSets.test.output + project.sourceSets.main.output
                     }
}
dependencies {
        compile project(':'proj1')
        compile project(':proj2')
        compile project(':proj3')
        compile group:'proprietarylib', name: 'hsqldb', version: '1.8.0.8', configuration: 'runtime'
}
test.doFirst {
         println "Test classpath is:- "
         sourceSets.test.runtimeClasspath.getFiles().each { file ->
          println "classpath damn file: \"" + file + "\""
  test {
        systemProperty "testDataDir", "${buildDir}/resources/test"
        include "**/*Test*.class"
        systemProperty "main.tests.data.build.dir", "${buildDir}/resources/test"
}

(Petula Guimaraes) #4

Btw, here i am just trying the code without tag enclosure to see if it posts correctly, as above my code seems duplicated ans making no sense:

sourceSets {

main {

java.srcDirs = [ ‘src/packages’]

resources.srcDirs = [ ‘src/packages’, ‘src’ ]

compileClasspath = compileClasspath + configurations.legacy

runtimeClasspath = project.sourceSets.main.compileClasspath +

project.sourceSets.test.compileClasspath +

fileTree("${buildDir}/resources/test") + fileTree("${buildDir}/resources/main") +

project.sourceSets.test.output + project.sourceSets.main.output

}

test {

java.srcDirs = [ ‘src/tests/packages’]

resources.srcDirs = [ ‘src’ ]

runtimeClasspath = project.sourceSets.main.compileClasspath +

project.sourceSets.test.compileClasspath +

fileTree("${buildDir}/resources/test") + fileTree("${buildDir}/resources/main") +

project.sourceSets.test.output + project.sourceSets.main.output

} } dependencies {

compile project(’:‘proj1’)

compile project(’:proj2’)

compile project(’:proj3’)

compile group:‘proprietarylib’, name: ‘hsqldb’, version: ‘1.8.0.8’, configuration: ‘runtime’ } test.doFirst {

println "Test classpath is:- "

sourceSets.test.runtimeClasspath.getFiles().each { file ->

println “classpath damn file: “” + file + “”” } test {

systemProperty “testDataDir”, “${buildDir}/resources/test”

include “**/Test.class”

systemProperty “main.tests.data.build.dir”, “${buildDir}/resources/test” }


(Peter Niederwieser) #5

It’s impossible to answer this question without knowing details about how the resources get loaded.


(Petula Guimaraes) #6

Hi Peter,

Fair enough! So, I decided do print out paths in different moments of my build/test execution. Here is what I saw:

17:22:57.438 [QUIET] [system.out] >>>> build dir is /a/nyn166f2/vol/nyn166f2v4/u_t1395154848/dir/ird.trend/ird/trend/alternative/build/refdata
(...)
  17:22:57.417 [QUIET] [system.out] classpath file: "/a/nyn166f2/vol/nyn166f2v4/u_t1395154848/dir/ird.trend/ird/trend/alternative/src/refdata/src/xml/referencedata/global/cashflowProductSpecification.xml
(...)
  17:24:18.818 [DEBUG] [TestEventLogger] com.ugh.ird.refdata.test.XmlSerializationTest > testGlobalSerialization STANDARD_OUT
17:24:18.818 [DEBUG] [TestEventLogger]
   17:24:18.817 [Test worker] INFO
c.m.i.t.s.ServiceStartConditions - initialising storgeService in global.dev
17:24:18.818 [DEBUG] [TestEventLogger]
   >>>> Absolute path dir :/a/nyn166f2/vol/nyn166f2v4/u_t1395154848/dir/ird.trend/ird/trend/alternative/src/refdata/xml/referencedata
17:24:18.818 [DEBUG] [TestEventLogger]
   17:24:18.817 [Test worker] WARN
c.m.i.i.faults.FullDetailsException - exception: com.ugh.ird.refdata.storage.ReferenceStorageServiceException: ReferenceData directory does not exist xml/referencedata

One thing we can see here is that the classpath and build dir are in sync. No surprises as it was stated in the gradle code. However, we can see that the test execution is setting up its root in ${projectDir}.

Funny thing is that in eclipse, the execution sets ${projectDir} in [absolutePathHere]/refdata/src, while apparently during my gradle test execution is going for [absolutePathHere]/refdata

My tests load the files using JavaIO library. Snippet:

File dir = new File(directory);
            if (!dir.exists()) {
    // where directory is the relative path of xml/referencedata and this is where it fails

Anyway I can force a ${projectDir} to be the path I want, but in a “generic” way? Just remembering I have a multi-project, so that is happening to a few projects that rely in the same way of loading resources.

Thanks! Petula


(Petula Guimaraes) #7

I am explaining on the next reply. So I guess my problem is: Why does eclipse uses a projectDir of

[fullPath]/refdata/src While Gradle does [fullPath]/refdata

This is enough to break all the tests, as appending the desired data/config directories will result in an invalid path.

I am not setting projectDir anywhere in the project, as I have several projects in a Gradle multi-project build and I wanted to keep such variables generic.


(Petula Guimaraes) #8

I guess your question made me go in the right direction. reading http://www.gradle.org/docs/current/userguide/writing_build_scripts.html

I realized that my build scripts are under /refdata, not under /refdata/src. That explains it all. Gradle sets project root under /refdata only.

Just the second question still remains: can I trick this variable somehow to go down one more folder, but in a generic way?


(Petula Guimaraes) #9

I guess I found out what I needed. I had no idea settings.xml can be so powerful…

So I needed something like this:

rootProject.name = 'alternative'
  println ">>>>root project name"
println rootProject.name
  include 'projA'
include 'projB'
  include 'refdata'
project(':refdata').projectDir = new File(settingsDir, '../src/refdata/src')
project(':refdata').buildFileName = 'build.gradle'
  println ">>>> refdata proj dir"
println project(':refdata').projectDir
  include 'proj1'
include 'proj2'
include 'proj3'

(Petula Guimaraes) #10

Hi there,

I have a problem now. As I was executing the task build only because of the long time my projects take, I now decided to go for a clean build and it does not seem to work.

Apparently now that I updated my settings.xml Gradle is no longer generating my compiled classes, resources, etc. My build directory contains only the structure

–/build -----/refdata --------/libs --------/tmp

And they do not even contain anything much useful.

What am I missing here?


(Petula Guimaraes) #11

I found out in this one as well.

It turns out that having the following in my settings.gradle

project(':refdata').projectDir = new File(settingsDir, '../src/refdata/src')
project(':refdata').buildFileName = 'build.gradle'

Changes my source and resourcedirs in build.gradle. they now have to start from the perspective of /refdata/src, not onlty /refdata.

So now they are:

sourceSets {
           main {
                java.srcDirs = [ 'packages']
                resources.srcDirs = [ 'packages', 'xml' ]

etc.


(Petula Guimaraes) #12

I found out in this one as well.

It turns out that having the following in my settings.gradle

project(':refdata').projectDir = new File(settingsDir, '../src/refdata/src')
project(':refdata').buildFileName = 'build.gradle'

Changes my source and resourcedirs in build.gradle. they now have to start from the perspective of /refdata/src, not onlty /refdata.

So now they are:

sourceSets {
           main {
                java.srcDirs = [ 'packages']
                resources.srcDirs = [ 'packages', 'xml' ]

etc.