Gradle plugin development
We recommend having a good understanding of the Gradle plugin development process explained in the core documentation.
This chapter focuses on plugin development enhancement provided by dev.gradleplugins.*
plugins and maintained by the Nokee team.
It bridges a fundamental gap in the plugin development experience offered by the Gradle team.
The plugins offer more modelling to ensure a more enjoyable development experience.
Introduction
We offer two Gradle plugin development plugins: dev.gradleplugins.java-gradle-plugin
and dev.gradleplugins.groovy-gradle-plugin
.
The plugins support Gradle plugin development for the Java and Groovy languages, respectively. [1]
When we only require compatibility functionality of plugin development workflow, we recommend applying the dev.gradleplugins.gradle-plugin-development
in the settings script.
It offers global conveniences to all projects, such as creating versioned Gradle API dependencies with source access.
Finally, we also offer two test suite plugins: dev.gradleplugins.gradle-plugin-unit-test
and dev.gradleplugins.gradle-plugins-functional-test
.
The plugins support unit and functional testing, respectively, for the Gradle plugin under development.
Minimum Gradle version
The plugins extend the familiar gradlePlugin
extension by adding the nested compatibility
extension.
This new extension model the minimum Gradle version supported by the plugins under development.
By default, it uses the current running Gradle version.
However, you can set it to any globally available Gradle distribution after and including 2.14.
gradlePlugin {
compatibility {
minimumGradleVersion = '4.9'
}
}
gradlePlugin {
compatibility {
minimumGradleVersion.set("4.9")
}
}
The plugin uses this new information to automatically configure the Java source and target compatibility to the minimum supported Java version for the target Gradle. For example, setting a minimum Gradle version of 5.0 or newer, the plugin will configure the Java compatibilities to Java 8. Rest assured, the plugins honours any override to the Java compatibilities.
When developing a Gradle plugin implemented in Groovy using dev.gradleplugins.groovy-gradle-plugin
, the plugin adds a dependency to groovy-all
based on the minimum Gradle version to the compileOnly
configuration.
For example, by setting the minimum Gradle version to 6.2, the Groovy runtime will be set to 2.5.8.
Gradle runtime compatibility information
All the Gradle runtime compatibility knowledge is accessible via the GradleRuntimeCompatibility
class.
Developers can query the following information for any previously released Gradle distribution:
-
Minimum Java version supported by a specific Gradle distribution, and;
-
Groovy, as well as Kotlin, if available, version packaged in a specific Gradle distribution.
This information is particularly useful when developing a library targeting the Gradle distribution. For each of the JVM languages, we need to align the runtime to ensure maximum compatibility.
We extract the compatibility information for each version manually. We welcome any pull request that would automate this information gathering and/or include newer/older runtime information. |
Redistributed Gradle API artifacts
The redistributed Gradle API serves the purpose of targeting a different Gradle version than the currently running Gradle.
We host every redistributed Gradle API artifacts under the dev.gradleplugins:gradle-api
coordinate.
Each artifact includes a source JAR for improved IDE experience.
A developer can depend on dev.gradleplugins:gradle-api:4.9
to target Gradle API 4.9 while running its build using a newer (or older) Gradle distribution.
The dev.gradleplugins.gradle-plugin-development
settings plugin adds the gradleApi(version)
extension method to the DependencyHandler
instance of each project:
dependencies {
compileOnly gradleApi('4.9')
}
dependencies {
compileOnly(gradleApi("4.9"))
}
Always declare Gradle API dependency as compile only dependencies.
If not, when executing the plugin inside Gradle, it will unnecessarily pull a complete copy of the Gradle classes.
You should only every declare a runtime dependency on the Gradle API if you need to execute against Gradle runtime, such as using ProjectBuilder for unit testing.
See the unit testing section to learn more.
|
We only redistribute the Gradle API artifact for Gradle 2.14 and newer. If you need access to older Gradle API artifacts, please open an issue on the GitHub project. |
Gradle plugin testing
We offer two plugins for testing Gradle plugins: dev.gradleplugins.gradle-plugin-unit-test
and dev.gradleplugin.gradle-plugin-functional-test
.
Both plugins have similar functionalities and differ in their testing goal.
We can select the testing framework for each test suites by adding a dependency.
We recommend using the dependencies
script block of each test suites.
The test suite dependency block offers convenient methods to add common dependencies quickly.
For example, we can use spockFramework()
method to create a dependency on the Spock Framework.
To specify a specific version for the Spock dependency, we can use spockFramework(version)
method.
By selecting the Spock Framework, the plugin automatically apply the groovy-base
plugin to enable Groovy compilation on the project.
Unit testing (e.g. dev.gradleplugins.gradle-plugin-unit-test
)
Unit tests for Gradle plugins focus on individual classes.
It validates the configurations of the plugin.
We usually use the ProjectBuilder
for this validation.
The unit test suite will automatically add an implementation dependency to the Gradle API.
The test suite is configurable via the test
extension on the project.
We can execute the test suite via the Test
task named test
.
Functional testing (e.g. dev.gradleplugins.gradle-plugin-functional-test
)
Functional tests for Gradle plugins focus on execution behaviours.
It validates how the tasks behave during execution, among other runtime checks.
We usually use the Gradle TestKit for this validation.
The test suite is configurable via the functionalTest
extension on the project.
We can execute the test suite via the Test
task named functionalTest
.
Testing strategies
We configure the testing coverage of Gradle plugins regarding Gradle distribution through the testing strategies.
The test suite plugins configure distinct Test
tasks for each testing coverage.
The plugin passes the selected Gradle distribution information to test against via the dev.gradleplugins.defaultGradleVersion
system property.
The value is a string representing a Gradle distribution version, i.e. 6.2.1.
There are three strategies available via the strategies
factory method in each test suite extension:
-
Minimum Gradle version (e.g.
coverageForMinimumVersion
): The minimum Gradle version supported by the plugins as configured on thecompatibility
extension. -
Latest global available version (e.g.
coverageForLatestGlobalAvailableVersion
): The latest released Gradle version as declared by the services.gradle.org end point. -
Latest nightly version (e.g.
coverageForLatestNightlyVersion
): The latest published Gradle nightly version from master as declared by the services.gradle.org end point.
At runtime, it’s up to the testing fixtures to honour the selected Gradle distribution under test as declared via the dev.gradleplugins.defaultGradleVersion
system property.
The Nokee team maintains testing strategies-aware Gradle fixtures, which automatically honour the distribution under test system property.
We can add a dependency on the Gradle fixtures using gradleFixtures()
method from inside the test suite dependencies
script block.
Other test fixtures, such as the plain Gradle TestKit, requires manual configurations of the distribution under test.
In the absence of testing strategies, the dev.gradleplugins.defaultGradleVersion system property is unset, thus defaulting to the test fixtures default distribution under test.
|
The Test
task names will include a suffix differentiating each strategy when we configure multiple testing strategies.
It allows quick and easy execution, even from the IDE:
Gradle test fixtures
The Gradle fixtures maintained by the Nokee team is a set of commonly needed APIs for testing Gradle plugins. It supports multiple executer types (i.e. Gradle wrapper, TestKit Gradle runner) and provides better assertion for Gradle results such as asserting executed and skipped tasks as well as asserting failures. It provides better assertions for common artifacts produced by Gradle, such as files, archives, and published artifacts in Maven repositories. It includes source elements for composing samples to use during testing. It also provides fixtures for asserting native binaries produced by Gradle.
The fixtures are in beta and may not be forward binary compatible. |
What’s next?
You should now have a grasp on the improvement offered by the dev.gradleplugins.*
plugins.
Head over the Gradle plugin development samples to see a demonstration of the plugins for common scenarios.
You can learn more on each specific Gradle plugin development plugins in the plugin reference chapters.
Help improve this chapter
Have feedback or a question? Found a typo? Is something unclear? Help is just a GitHub issue away. Please open an issue or create a pull request, and we’ll get back to you.
kotlin-dsl
plugin behave differently, which prevents from adding supporting for Gradle plugins implemented in Kotlin.