How to run filtering tests in gradle? - gradle

I have to run tests in a specific order using build.gradle file.
I have the build.gradle file looks like the following:
test {
include 'com.my-project.MyTestClass'
include 'com.my-project.MyTestClass1'
}
but when I running test task I have the following message:
Tests event were not received
How can I fix this problem?

That message just means that no tests were actually run. There could be a number of reasons for that, but the most likely given your example is that the include method takes an Ant style file pattern, but you have given it (fully qualified) class names. Also, 'my-project' is not a valid package name, but I assume this is just a error in your example here.
But more importantly, if your intent is to run tests in a specific order, you will not achieve that with a single test task. The specified includes just tell Gradle what tests are part of the suite, but doesn't affect the order.
I don't know what test framework you are using, but I also don't think it is possible with JUnit 4 and 5. The only way I can think of is to create multiple Test tasks in Gradle, where each task represent a single unit test (or group of tests that can be run in any order), and where you order each task through dependsOn. So something like this:
task myTest1(type: Test) {
include 'example/MyTestClass1.class'
}
task myTest2(type: Test) {
dependsOn myTest1
include 'example/MyTestClass2.class'
}
test {
exclude 'example/**'
dependsOn myTest2
}

Related

Confused about Gradle delete task

I'm currently learning Gradle, so this is probably a simple question but I can't seem to understand.
I need to create a task in my gradle build that deletes a set of intermediate files. So after a bunch of Google'ing, I tried the following:
task deleteTest (type: Delete) {
doLast {
delete fileTree ('src/main/gen') {
include '**/*'
}
}
}
This has no effect, since when I run the task all of the files in the 'src/main/gen' directory still exist. From reading various websites, it seemed like this was the correct approach, but it just doesn't work.
Just for grins, I tried:
task deleteTest (type: Delete) {
delete fileTree ('src/main/gen') {
include '**/*'
}
}
This seems to work, all of the files get removed from the directory(although it leaves empty sub-directories, which I also don't understand). But from what I read, this is not the correct way to go, since it executes during configuration, not during execution.
Can someone please explain this to me? There's apparently something I'm just not grokking with respect to Gradle in general and this problem in particular.
The short answer:
If you just want to delete the folder src/main/gen and everything inside, use something like this:
task deleteTest(type: Delete) {
delete 'src/main/gen'
}
Your second example is fine, too. It preserves directories because a fileTree is used, which only collects files.
The long answer:
Your first example mixes the two ways to delete files in Gradle. The first one is to use a task of type Delete, the second one is to invoke the method delete of the type Project. But how to they differ and why are they mixed in your example?
Gradle is based on its task system that allows to define and configure tasks which are only run if necessary. Whether a task is required for the build will be determined from task dependencies (dependsOn). This is the reason why Gradle distinguishes between the configuration phase and the execution phase. During configuration phase, the whole build script gets executed except the actual task actions (not visible in the build script) and code wrapped in doFirst / doLast closures. During execution phase, each required task gets run by Gradle. This involved executing the doFirst closures of the task, then the actual task actions and in the end the doLast closures of the task. Now for a Delete task like the one above this means, that the code in the configuration closure delete 'src/main/gen' gets executed during configuration phase, but the actual deletion of the files (the task action) happens later on, during execution phase.
The problem with this approach arises when its required to delete files directly or all the time (e.g. in a plugin or another scenario). It would be too complicated to create a task, setup the dependencies and so on. Here comes the method delete of the type Project to the rescue. It provides the same interface for configuration as the task type Delete, but executes directly. It can be called via the project instance (e.g. project.delete 'src/main/gen') everywhere in your script and runs instantly, but because the project instance is used as scope of the whole script, just using delete is sufficient, too. Well, it is not always sufficient. If the current scope provides a method called delete (with the same signature), this method will be used instead. This is the case inside a task of type Delete and this is the reason why your first script does not work:
Your task of type Delete gets configured in the doLast closure, which runs after the actual deletion should have taken place. If you remove the type: Delete, the method delete will no longer configure the task, but instead delete the files instantly because it is no longer the method delete of the task Delete, but the method delete of the type Project. This works fine, but using a real task should be preferred.
If you remove the type: Delete from your second example, the same thing will happen. Instead of configuring the task, the files will be deleted instantly (now during configuration phase). You do not want this behavior, because the task will be obsolete, since the files will be deleted every time Gradle is invoked. This is what you mentioned as a possible problem.

Recommended way of plugin configuration with "tasks.withType(Foo) {...}" or "foo {...}"?

I'm learning Gradle and am confused to see two styles of how plugins are configured, depending on which tutorial/book I read:
checkstyle {
ignoreFailures = true
}
tasks.withType(Checkstyle) {
ignoreFailures = true
}
The first one looks cleaner but the second one would also apply to custom tasks that inherit from "Checkstyle". I suspect that the latter makes it easier for the IDE to guess the type and allow proper auto completion, is that right?
Is there a general trend towards one or the other that I should follow?
The two are slightly different
checkstyle {...} will configure a single task named "checkstyle". It will fail if a task named "checkstyle" does not exist
tasks.withType(Checkstyle) {...} will configure any tasks in the project of type Checkstyle. This could result in zero, one or multiple task instances being configured.

How to determine if a Gradle task was instantiated (Configuration Avoidance API)

I am trying to improve the performance of our Gradle builds and discovered the Gradle Task Configuration Avoidance API (https://docs.gradle.org/current/userguide/task_configuration_avoidance.html). It allows to postpone the creation and configuration of a task, unless it is really needed. This might save a lot of startup time and as we call Gradle multiple times during a build, this could amount to considerable time savings.
We developed some plugins for internal use and I put an effort into changing how I define the tasks to avoid creation when not needed. I want to test if my changes are successful and the task instantiation is delayed.
Simple example of how to create a task without instantiating it:
class MyTask extends DefaultTask {
}
TaskProvider customTask = tasks.register("customAction", MyTask) {
println "task configured!" // configuration time output
doLast {
println "action 1!" // execution time output
}
}
// configuration like this avoids task instantiation
tasks.named("customAction") {
doLast {
println "action 2!"
}
}
tasks.withType(MyTask).configureEach {
doLast {
println "action 3!"
}
}
Executing gradle help does not print the "task configured!" message, while gradle customAction does.
To make sure I do not accidentally trigger task instantiation, I would like to write tests for our plugins. But I could not find a way to determine if a task is instantiated or not.
I know about Build Scans (https://guides.gradle.org/creating-build-scans/), but our corporate guidelines are strict and clearance is pending, so I can not use it for now. Also, I do not see a way to use it in tests.
Is there a way to
get a list of created/instantiated tasks from the Gradle project?
or is there any property on Task or TaskProvider showing whether the task has been created/instantiated?
or can buildscans be used offline somehow?
It would be cool, if the solution could be used in the plugin's test code, but manual evaluation would also be valuable.
configureEach called only when task is created. you can write something like this to get list of all configured tasks
def tasks = []
project.allprojects { Project sp ->
sp.tasks.configureEach { Task t ->
tasks,add(t.path)
}
}
project.gradle.buildFinished {
println tasks
}
This is not exactly what OP asked for, but this will give you some stats on how many of each type of task were configured:
gradlew :help -Dorg.gradle.internal.tasks.stats

Referencing the outputs of a task in another project in Gradle

Consider the following setup
rootProject
|--projectA
|--projectB
There is a task taskB in projectB and I would like the reference the outputs of that task in a copy task taskA in projectA. For example, taskA might look something like:
task taskA(type: Copy) {
dependsOn ':projectB:taskB'
from ':projectB:taskB.outputs'
into 'someFolder'
}
Of course the above example doesn't actually work. While it's okay to reference the task as :projectB:taskB as a dependency, :projectB:taskB.outputs doesn't seem to mean anything to Gradle. I've tried reading through the Gradle docs but didn't find anything that referenced what I'm trying to do.
The accepted answer has been to only and recommended way to solve this problem. However building up this kind of project dependencies and reaching from one project into another is discouraged by the Gradle team now. Instead of this, projects should only interact with each others using publication variants. So the idiomatic (but sadly at the moment more verbose) way would be:
On the producing side (projectB) define a configuration that is not resolvable but consumable by other projects and creates a new variant (called taskB-variant)
configurations.create("taskElements") {
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage::class, "taskB-variant"))
}
outgoing.artifact(taskB.outputs)
}
On the consuming side (projectA) define a configuration that is resolvable but not consumable for the same variant and define a dependency to projectB
val taskOutputs by configurations.creating {
isCanBeResolved = true
isCanBeConsumed = false
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage::class, "taskB-variant"))
}
}
dependencies {
taskOutputs(project(":projectB"))
}
tasks.register<Copy>("taskA") {
from taskOutputs
into 'someFolder'
}
This way you decouple how the outputs are produced and the publication variant (called "taskB-variant") becomes the interface between projectA and projectB. So whenever you change the way the output is created you only need to refactor projectB but not projectA as long as you make sure the outputs end up in the taskElements configuration.
At the moment this is still pretty verbose but hopefully Gradle will get more powerful APIs to describe this kind of project relationships in the future.
projectA build.gradle should be:
evaluationDependsOn(':projectB')
task taskA(type:Copy, dependsOn:':projectB:taskB'){
from tasks.getByPath(':projectB:taskB').outputs
into 'someFolder'
}

How to declare dependencies of a Gradle custom task?

If I've created a custom task:
class MyTask extends DefaultTask {
...
}
I can at another time create an instance and declare dependencies:
task(["type": MyTask, "dependsOn": importantThing], "MyTaskName")
However, it seems a bit weird to separate the task definition from the declaration of dependencies. That is, it seems like everything defining the task should be in one place, or else it would be easy to instantiate the task without the right dependencies. Is there some better way to do this?
Tasks should be generic and self-contained. They should only operate on their own input properties, and should not assume existence of other tasks. Declaring tasks and their dependencies is the responsibility of build scripts and/or plugins.

Resources