How Can I Write An Integration Test For A Gradle Plugin - gradle

I'm writing a plugin for Gradle. It's a port of a Maven plugin, which I testing using the Maven integration testing plugin. I'd like to create a series of tests for different build.gradle files.
Is there a good way to do this is Gradle (as what I have does not seem to work).

Yes, the easiest way to make a simple test is use the org.gradle.testfixtures.ProjectBuilder class.
Project project = ProjectBuilder.builder().build()
project.apply plugin: 'dependencyAnalysis'
project.apply plugin: 'java'
assertTrue(project.tasks.analyze instanceof AnalyzeTask)
This can however only test up to and including the configuration phase. So for a test of the execution phase this will not work.
You can also use the tooling API like Opal suggested, but I would suggest that you use it through the nebula test plugin. https://github.com/nebula-plugins/nebula-test

The Gradle TestKit has recently been added to the Gradle distribution to help with integration testing. At the time of writing it has some missing features but I have used it and it is very useful. I have not used nebula-test so cannot compare them.

Related

Gradle Composite Build: How to configure Tasks for all included builds

I am new to gradle composite builds. I have a multi-project build that uses precompiled script plugins in order to have tasks configured for all projects that include the plugin. Now I want to port that functionality to a composite build setup.
The screenshots below show how the current multi-project build works:
This java precompiled script plugin (/buildSrc/.../java-conventions.gradle.kts) configures the "JavaCompile" tasks (i.e. sourceCompatability, targetCompatability...).
This kotlin precompiled script plugin imports the java conventions plugin and configures the "KotlinCompile" tasks.
Applying the the kotlin conventions plugin to project "test" automagically sets up my project with the proper "JavaCompile" and "KotlinCompile" configuration as shown above.
I have read the official docs and tutorials on gradle composite builds. Still, I dont know the proper way how to do this with composite builds. Do I have to write standalone plugins for this? If so, can you provide a POC code snippet? Any advice is greatly appreciated!

Should I shadow Kotlin when writing a Gradle Plugin

I'm writing a plugin to extract some boilerplate from a selection of existing Gradle build scripts. The existing build scripts are primarily written in Groovy and compiling Java.
To build my plugin I'm using the Gradle Kotlin DSL and figured I'd take the opportunity to write the plugin in Kotlin too. This all works but now my plugin has a huge dependency on Kotlin - and the Gradle docs specifically recommend minimizing external libraries.
Java and Groovy plugins avoid this because Java & Groovy are a shared dependency with Gradle, but Kotlin isn't a shared pre-requirement and so we then have to be concerned about potentially conflicting Kotlin versions needed by different plugins.
I figure I should move forward with one of the following approaches but am not clear which:
Just list Kotlin's stdlib as a standard dependency and trust Gradle to sort things out.
This works for one plugin, but should I expect problems when another plugin is also being used but depending on a different Kotlin?
Build some sort of uber shadowJar shadowing Kotlin libraries for my plugin
Implying that every plugin I write like this will be 10s of MB bigger than necessary.
Give up on Kotlin based plugins and rewrite in Java/Groovy
Would be a shame to give up on the new goodness but might be better to avoid the above sins.
Recommendations welcome!
Since your plugin is replacing boilerplate and is presumably not destined for public release, would it make sense to write it as a script plugin in the Gradle Kotlin DSL? That way a new enough Gradle should be able to understand it natively.
Raised this in Gradle Community Slack and was recommended to use Gradle's kotlin-dsl plugin to automatically configure dependencies on gradleApi() and embeddedKotlin() versions, and therefore whatever Kotlin version is bundled with Gradle's Kotlin DSL support.
I was concerned that this might introduce a dependency on the calling script using Kotlin DSL, but I've tested with a Groovy script and have been able to use my plugin. I assume that it does still depend on a version of Gradle with Kotlin DSL support though - i.e. 4.0+.

What is the difference between an app dependency and a module dependency/plugin?

When using some 3rd party libraries, I add a dependency to my module's build.gradle file.
compile 'com.android.support:appcompat-v7:24.1.1'
Or I add a plugin
apply plugin: 'com.neenbedankt.android-apt'
Some other times, the library requires adding a dependency to my app's build.gradle file.
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
What is the difference between these dependencies and plugins?
Why can't they all be set in a single build.gradle file?
All suggestions are appreciated, I'm having trouble searching for info on this
Three things. Gradle plugin, module dependency, a build dependency which is placed on the classpath of the build tool.
A plugin is how Gradle knows what tasks to use. There are many plugins. For more info, see Gradle - Plugin Documentation
A dependency is a library that is compiled with your code. The following line makes your module depend on the Android AppCompat V7 library. For the most part, you search Maven or Jcenter for these.
compile 'com.android.support:appcompat-v7:24.1.1'
The classpath setting is needed for Gradle, not your app. For example, this allows this includes the Gradle Build Tools for Android into the classpath, and allows Gradle to build apps.
classpath 'com.android.tools.build:gradle:2.1.2'
Why can't they all be in one build.gradle file?
They probably can be. It is simply more modular to not.
I got this answer from a colleague, and this helped me understand. "A gradle plugin is like the tools you use to build the app. The dependencies are the libraries included in the app. A gradle plugin is usually the tasks - like ktlint, etc."
I didn't understand this myself so here is what i found. My answer is based on gradle build tool.
Plugins:
Add additional tasks, repositories, new DSL elements, configuration for classpaths/build/run or dependency management for subsequent development. Plugins are developed for a larger scope of development like java, kotlin or spring-boot.
Dependencies:
modules/libraries for tasks like http, serialization or database are dependencies stored remotely at repositories or locally that are needed at runTime, test or build are resolved by gradle in a configured fashion.
Sources:
Spring boot gradle plugin: https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin
Gradle documentation on plugins/dependencies: https://docs.gradle.org/current/userguide/plugins.html
https://docs.gradle.org/current/userguide/core_dependency_management.html
Remote repositories:
https://mvnrepository.com/
In simple words:
Plugins are used to add some additonal features to the software/tools(like Gradle). Gradle will use the added plugins at the time of building the App.
Dependecies are used to add some addtional code to your source code, so a dependency will make some extra code (like Classes in Java) in the form of library available for your source code.

How do I get the plugins applied to a build script using gradle tooling api?

I'm writing an Eclipse plugin and I want to use the gradle tooling api to inspect a gradle project's build script to look whether or not it has certain plugins applied.
Lets say that I have a build script that looks something like this:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.dm.gradle:gradle-bundle-plugin:0.6.2'
}
}
apply plugin: 'java'
apply plugin: 'org.dm.bundle'
repositories {
mavenCentral()
}
sourceCompatibility = 1.7
version = '1.0'
Is there a way that I can use the gradle tooling api to find out which plugins this particular gradle project was applying?
I know that you can get the list of project dependencies, but what about the buildscript{} dependencies?
This question has actually two separate questions embedded in it. I didn't realize at the time. The first question should be:
1. How do you use the tooling-api to find out of a particular project has applied a particular plugin?
The answer to this question is handled precisely here: Gradle Tooling API Feature
You can find the source code used in that article here: Tooling API Example Repo
However I had some trouble getting that example to build and execute locally so I posted a fix to my own fork if you want to use it.
Then the 2nd question is this:
Once you have the necessary tooling-api model and plugin from question #1, how do you execute this custom tooling script from an Eclipse plugin context?
For this you will need to use the excellent gradle integration plugin for Eclipse as a dependency for your own eclipse plugin. Once this is configured you can simply import these APIs GradleConnector, ProjectConnection, ModelBuilder that are exported by the gradle plugin for eclipse already mentioned.
Getting your own local custom model on the classpath is as easy as embedding the jar in your eclipse plugin as per normal mechanisms (MANIFEST.MF entry, don't forget build.properties to include the jar). Also you will need to have a local repo available for the custom gradle script to pickup the model/plugin classes as show in the example github repo

Can I use a Maven plugin (enunciate) in Gradle?

I have a maven plugin called enunciate that generates nice API documentation. I'd rather use Gradle as my build tool but it looks like it's limited in this aspect or maybe I just don't know how to use it.
I'm wondering if it's possible to use a maven plugin (enunciate) in gradle somehow? Do I have to write an ant script and call that? So far I can't find a gradle example for enunciate so I'm guessing it's not supported?
You can't use a Maven plugin as-is in Gradle; you'll have to port it to a Gradle plugin. How difficult this is depends on how many Maven APIs the plugin is using. Another strategy might be to call into Maven via Gradle's Exec task.
As of October 2015, a Gradle plugin for Enunciate is available.
https://github.com/stoicflame/enunciate-gradle

Resources