Search code examples
javaeclipsegradlebuildship

Eclipse (2023-12) + Buildship - Incorrect classpath when importing test artifact from project library


Basically I have 2 projects .

  • Lib2 contains code and test utils. These test utils are classes that should be made available to other projects to instrument their tests.
  • Lib3 has some code (that's using Lib2) and tests that uses the test utils from Lib2 (in this case it's a library, but the problem arises when it's an 'application' as well)

When the Lib3 project is imported/refreshed, eclipse generates a wrong classpath, basically it includes Lib2 in the following way:

enter image description here

As you can see it's only visible to tests sources BUT withtout test code. The result is that it's totally useless, since I need part of it to instrument the tests and part of it for the code. So, all the import fails (in main and in test).

Relevant gradle configuration:

Lib2:

apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'eclipse'

//Test Utils Part
sourceSets {
  testUtils {
    compileClasspath += sourceSets.main.output
    runtimeClasspath += sourceSets.main.output
  }
  test {
    compileClasspath += sourceSets.testUtils.output
    runtimeClasspath += sourceSets.testUtils.output
  }
}

/*
 * To compile testUtils sourceSet we need to exends the configuration for the 'main' sourceSet.
 * And, since we define dependencies only for testUtils, test must have to extends from it.
 */
configurations {
    testUtilsImplementation.extendsFrom implementation
    testUtilsRuntime.extendsFrom runtime
    testCompile.extendsFrom testUtilsImplementation
    testImplementation.extendsFrom testUtilsImplementation
}

configurations {
    testUtilsArtifacts.extendsFrom testUtilsImplementation
}

task testUtilsJar(type: Jar) {
    archiveClassifier.set("test")
    from sourceSets.testUtils.output
}

artifacts {
    testUtilsArtifacts testUtilsJar
}

// End test utils part

Lib3:

apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'eclipse'

repositories {
     mavenCentral()
}

dependencies {
      /*Leo*/
    api project(":Lib2")
    testImplementation project(path: ":Lib2", configuration: 'testUtilsArtifacts')    
 }

and settings.gradle

include (":Lib2")
project(":Lib2").projectDir = file("../Lib2")

It seems a pretty basic configuration, I don't understand why it doesn't work anymore. I believe that I should tweak something using the eclipse plugin but I have no idea where to start.


Solution

  • In the Gradle Forums, I've got the following answer from Ole Osterhagen which works for me:

    In order to expose test classes to dependent projects, you have to append this to your build.gradle of Lib2:

    eclipse {
        classpath {
            containsTestFixtures = true
        }
    }
    

    After a refresh the property without test code for the dependency from Lib3 to Lib2 should disappear.

    Unfortunately, the other property Visible only for test sources requires an ugly workaround in build.gradle of Lib3:

    eclipse {
        classpath {
            file {
                whenMerged {
                    // the path '/Lib2' may need to be adjusted to your actual directory structure
                    entries.findAll { it.path == '/Lib2' }.each { it.entryAttributes['test'] = 'false' }
                }
            }
        }
    }
    

    See also EclipseClasspath in the DSL reference.