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

Recently we made the big jump from java 8 to java 20, gradle 4.6 to gradle 8.6, and eclipse Neon (2018) to Eclipse 2023.

This is to say that the project structure is a bit old and I made a big jump between eclipse versions.

The problem is only in eclipse: from command line everything is ok.

Basically I have 2 libraries.

  • Lib2 contains some code and some test utils. These test utils are classes that should be made available to other project to instrument their tests.
  • Lib3 has some code (using Lib2) and tests that uses the test utils from Lib2

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.

I can add, that the big jump in java/eclipse version has nothing to do with the problem. What I’m showing is what happens with two brand new projects

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 {
                entries.findAll { it.path == '/Lib2' }.each { it.entryAttributes['test'] = 'false' }
            }
        }
    }
}

See also EclipseClasspath in the DSL reference.

Great, it works, thanks!

1 Like