Why doesn't matching work here but configureeach works?

I posted this question on SO but did not get an answer yet.

I want to add tests of all flavors to a meta task. This does not work:

subprojects {

 task("testAllFlavors"){
    val buildTask = this
    tasks.matching {
        name.startsWith("test") && name.endsWith("DebugUnitTest")
        }.all {
        buildTask.dependsOn(this)
}
}

And this also does not work:

subprojects {

 task("testAllFlavors"){
setDependsOn(tasks.matching {
           name.startsWith("test") && name.endsWith("DebugUnitTest")
        })
}
}

But this does work:

subprojects {
 task("testAllFlavors"){
 val buildTask = this
        tasks.all {
            if(name.startsWith("test") && name.endsWith("DebugUnitTest")) {
                buildTask.dependsOn(this)
            }
        }
    }


}

What is the difference between the 3 options? The look the same to me? Why does just the third option work ? I use gradle 7.1 and AGP 4.2

Inside the “matching” this is not what you think.
It is the testAllFlavors task, so you always check the name of that and thus your condition is always false.
You would need it.name....
Within the all on the other hand, the this is the “inner” task which is why your 3rd variant works.

But all your versions have one big drawback, they cause each and every task to be realized, because to check the name in the matching or all, the task needs to be realized of course, so task-configuration avoidance is prevented.

You should at least match the task by type first to at least limit the tasks that need to be realized to all of that type and then check for their name and you also don’t need to use all, but can just give the filtered task collection to the dependsOn, so something like this:

tasks.register("testAllFlavors") {
    dependsOn(tasks.withType<AbstractTestTask>().matching {
        it.name.startsWith("test") && it.name.endsWith("DebugUnitTest")
    })
}
1 Like

Thanks. You saved my day.