Claude Brisson
04/28/2025, 4:19 AMorg.gradle.testfixtures.ProjectBuilder().build()
), and to other test-only modules.
Using the buildSrc
strategy or the includeBuild
strategy for the custom plugin module itself are not suitable for this plugin module since it does split the build configuration and make it much harder to mutualize configuration, resources, versions, etc. So I am expecting the custom module plugin to be a standard module among the others, in the same build unit. But the tests modules could be somehow separated, I guess.
What are the applicable build architectures for defining, testing and applying a custom plugin that would not isolate the custom plugin module in a separate build context, yet have the custom plugin be visible to tests modules, and to its own tests source code?Vampire
04/28/2025, 6:42 AMClaude Brisson
04/28/2025, 7:54 AMexamples
folder (and to the test project in its own tests, but its tests could be moved elsewhere if that's more convenient).Thomas Broyer
04/28/2025, 8:26 AMexamples
could be their own build (rather than subprojects in your main build) that includeBuild
the parent folder.Claude Brisson
04/28/2025, 8:57 AMThomas Broyer
04/28/2025, 9:45 AMClaude Brisson
04/28/2025, 10:52 AMVampire
04/28/2025, 11:49 AMProjectBuilder
tests are not so much for functional tests as many moving parts are missing, but only for unit tests. In those you can just apply the plugin, yes.
To centralize versions, you can for example use version catalogs, that is the built-in way to centralize version definitions and you can use the same version catalog from the plugin build and the example builds by referencing the catalog file manually.
To centralize common build logic, you would put that build logic to yet another separate build that you then include from the example builds and the main build.Claude Brisson
04/28/2025, 2:33 PMVampire
04/28/2025, 2:42 PMClaude Brisson
05/01/2025, 3:07 PMcommon
core (-> common)
api-client (-> common)
api-server (-> core)
plugin (-> core)
And if I want to add a test
module to it using the plugin, switching to a multi-project build brings a complete havoc to the structure, with test having to be a separate build, and what... including the build of the root project?! Having all modules being independant builds?! What about the incidences on dependencies, configuration, maven-publish, etc. It looks really weird.
There should be some way to explain to gradle at the configuration step that a specific module uses a plugin yet to be produced, or to somehow serialize the builds...
Of course, I can always have an entirely separated example project. The release process would then be;
⢠publish the main project on maven local
⢠check the build on the example project (the main point being that the example project, as well as providing examples to users, is heavily used in the plugin test cases)
⢠if it looks ok, publish the main project
There should be some way to internalize this process in gradle. For now, I will use this manual workaround.Thomas Broyer
05/01/2025, 3:41 PM./gradlew build
will both build the plugin and test it through other projects that apply it.
What you do want is to have a single command to both build the plugin and run functional tests, not necessarily have a single build that both builds and applies the plugin.
https://docs.gradle.org/current/userguide/testing_gradle_plugins.html#functional-testsThomas Broyer
05/01/2025, 3:43 PM--include-build ${projectPath}
(instead of a hard-coded includeBuild("../")
in the settings script)Claude Brisson
05/01/2025, 8:07 PMthe main build then runs those other builds (but does not include them), with TestKit or Examplar or something similar.Who does the publishing, then?
Vampire
05/01/2025, 9:38 PMswitching to a multi-project build brings a complete havoc to the structure,What do you mean by that? You just define a new project
test
, in which you include the other build with all the projects within pluginManagement { ... }
and can then just apply the plugin to your test project like normal.
Having all modules being independant builds?!You can do that, but there is no reason to do so. That's purely a question of how you want to structure your build.
What about the incidences on dependencies, configuration, maven-publish, etc. It looks really weird.I have no idea what "incidences" you talk about or what you might think "looks really weird" unless you more concretely describe your thoughts.
There should be some way to explain to gradle at the configuration step that a specific module uses a plugin yet to be produced, or to somehow serialize the builds...Sure, and you were just told the way. Composite build is exactly what you ask for. Within one build, no, there should not be such a configuration option, that would be very unclear, unmaintainable, fragile, and totally unnecessary complex when there already exists a proper and better way. :-)
Of course, I can always have an entirely separated example project. The release process would then be;⢠publish the main project on maven local ⢠check the build on the example project (the main point being that the example project, as well as providing examples to users, is heavily used in the plugin test cases) ⢠if it looks ok, publish the main project
There should be some way to internalize this process in gradle. For now, I will use this manual workaround.Well, whatever works for you, you have to live with the consequences. But a composite build is exactly what you are after. But if you refuse to use it and want to make your life much harder than it needs to be. š¤·āāļø That's your decision. š But at least if you use that approach, don't use Maven Local, but a dedicated local repository, or at least have it last in the list of repositories and always use a repository content filter. Maven Local is broken by design in Maven already, and it will make your builds slow, fragile, and flaky if used lightly. https://docs.gradle.org/8.9/userguide/declaring_repositories.html#sec:case-for-maven-local
Claude Brisson
05/02/2025, 1:07 PMtest
has its own build. You are suggesting that test
should reference the other projects in its pluginManagement
section but:
⢠does it mean that this section will have ncludeBuild
directives, hence having test
depends on the whole sources of the other projects? Do those other projects have to be removed from the main build, which would then just do an includeBuild
on test? If so, that's what I find a bit weird, as I'm expecting test
to only require a binary dependency on the plugin and other modules.
⢠or does it mean that test
will use Testkit in its functional tests (as we would do in the plugin unit tests) and that it will allow this binary dependency?
I'm still kindof in the dark...Thomas Broyer
05/02/2025, 8:18 PMtest
or example
or whatever folder and create a separate build in there that uses your plugin (you can plan on using a published binary, in which case include a version number). You should be able to use cd test && ./gradlew build --include-build=..
and it would then build the plugin (and core, as it's a dependency; only the required tasks to produces the classes and resources) project before adding them to the classloader of the test/example build (if you included a version number for the plugin, you could just build without the --include-build
and it would resolve it from the repository; otherwise, I would then add pluginManagement { includeBuild("..") }
to the test/settings.gradle.kts
to always use the parent build, and never a published artifact).
3. in your plugin
project, create a functional test suite that runs the test
project using TestKit; or use Examplar to do the same; possibly passing --include-build=${path}
if needed). Yes, it means that running the functional tests for the plugin will actually rebuild the plugin from an included build of a forked Gradle build! (also note that this functional test suite won't actually have a dependency on the plugin itself, we just co-locate it in the plugin project because that still represents tests of the plugin)
With that setup:
⢠./gradlew check
(./gradlew :plugin:functionalTest
) at the root will exercise the plugin by actually running another Gradle build of the test
build/project
⢠cd test && ./gradlew build
will run the test project, using the plugin; if you added an includeBuild("..")
in the settings script, then it'll compile the plugin and core projects from the root build to use them; otherwise it'll use a published binary (and you could add --include-build=..
on the command line to use the root build instead). Without the includeBuild("..")
in the settings script, this really serves as an example build that can be moved out of the code base and used as-is independently.
That's how I would do it, from what I understood of the information you shared.Claude Brisson
05/04/2025, 8:56 AMpluginManagement { includeBuild("..") }
in the to the test/settings.gradle.kts
does the trick for the configuration step, the next problem is that the test build does also depend on :common, adding another includeBuild("..")
outside of the pluginManagement
section does not seem to work (the project :common
is not found, neither is :examples:common
). Still searching...Claude Brisson
05/04/2025, 9:01 AMincludeBuild("..")
directives, would including the root project in the buildSrc
of the examples build work?Claude Brisson
05/04/2025, 9:17 AMexamples
...Thomas Broyer
05/04/2025, 10:17 AMproject(ā¦)
dependencies to reference projects of the included build from the including build, you need to rely on dependency substitution.Claude Brisson
05/05/2025, 10:43 PMClaude Brisson
05/07/2025, 7:08 AMpackage com.republicate.skorm
import org.gradle.testkit.runner.GradleRunner
import org.junit.Test
import java.io.File
class ExamplesTest {
@Test
fun bookshelfTest() {
val projectDir = File("../examples")
GradleRunner.create()
.withProjectDir(projectDir)
.withDebug(true)
// .withArguments("build")
// .withArguments(":bookshelf:build")
.forwardOutput()
.build()
}
}
No matter what, no error is reported, and the html report is empty...Claude Brisson
07/13/2025, 11:52 AM