0

I have a highly-modularized project and I would like to declare one more separate module for some special test suite. Also, I don't want to repeat declaration of any dependencies which are already in classpath of the main application's module, so I would like to extend one Gradle configuration (in other words "dependencies scope") from another (the same way any implementation dependency from src/main becomes visible to src/test in default case).

If I had a single module, I would just declare one more test suite with testing {} DSL and extend one configuration from another to inherit dependencies from src/main to src/myCustomTestSuite. And the following works as expected within the single module:

plugins {
    `java-library`
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("commons-codec:commons-codec:1.15")
}

testing {
    suites {
        val acceptanceTest by registering(JvmTestSuite::class) {
            description = "Runs acceptance tests."
            useJUnitJupiter()
        }
    }
}

val acceptanceTestImplementation by configurations.getting {
    extendsFrom(configurations.implementation.get()) // <-- ✅ 'commons-code' becomes available for my tests in `src/acceptanceTest`
}

The problem appears when I try to extend configuration located in another module. Suppose I have a Gradle project with 2 modules: foo and bar.

├── bar
│   ├── build.gradle.kts
│   └── src
│       └── acceptanceTest
│           └── java
│               └── example
│                   └── ExampleTest.java
├── build.gradle.kts
├── foo
│   └── build.gradle.kts
└── settings.gradle.kts
  • :foo module declares 'commons-codec' implementation-dependency for src/main
plugins {
    `java-library`
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("commons-codec:commons-codec:1.15")
}
  • Now in :bar I would like to create a special test suite inheriting dependencies from :foo.implementation:
plugins {
    `java-library`
}

repositories {
    mavenCentral()
}

testing {
    suites {
        val acceptanceTest by registering(JvmTestSuite::class) {
            useJUnitJupiter()
        }
    }
}


val acceptanceTestImplementation by configurations.getting {
    extendsFrom(project(":foo").configurations.implementation.get()) // <-- ❌ this one does not work as expected
}

Instead of an expected result, Gradle fails to initialize the project with an error at: bar/build.gradle.kts, saying:

FAILURE: Build failed with an exception.
...
Configuration with name 'implementation' not found.

I also have additional observation: If I rename :bar to :goo (which means it will be after :foo alphabetically), Gradle won't fail on initialization, but 'commons-code' won't be inherited to become visible for test code at :goo/src/accetpanceTest. Compilation of src/acceptanceTest/java/example/ExampleTest.java will fail with:

ExampleTest.java:3: error: package org.apache.commons.codec.binary does not exist

Looks like the problem appears because the configuration I want to inherit from gets evaluated lazily. How to fix that problem and achieve an expected result?

Kirill
  • 6,762
  • 4
  • 51
  • 81

0 Answers0