I would like to write a custom task for an Android application project with multiple Gradle modules which executes the unit tests in the following modules so I can run all of them with one Gradle task invocation:
- Android application module, e.g.
testOrangeDebugUnitTest
- Android library modules, e.g.
testDebug
- Java/Kotlin library modules, e.g.
test
Requirements
- It would be convenient to being able to configure one product flavor (e.g. “orange”) to being tested (running all would take too long).
- Also, running Android unit tests with the
debug
product type is sufficient. - Modules names should not be hardcoded so that the project is extensible and tests in new modules are picked up automatically.
Draft
Here is my work in progress approach:
// buildSrc/src/main/kotlin/com/example/TestAllModulesTask.kt
abstract class TestAllModulesTask : DefaultTask() {
private companion object {
val DISALLOWED_BUILD_TYPES = setOf("release")
val DISALLOWED_PRODUCT_FLAVORS = setOf("blue", "green")
}
private val allowedTestTasks = mutableListOf<Pair<Project, Test>>()
init {
project.subprojects
.forEach { subproject ->
subproject.tasks
.filterIsInstance<Test>()
.filter { !it.namedWithAny(DISALLOWED_BUILD_TYPES) }
.filter { !it.namedWithAny(DISALLOWED_PRODUCT_FLAVORS) }
.forEach { task ->
println(":${subproject.name}:${task.name}")
allowedTestTasks.add(subproject to task)
}
}
}
override fun getDescription(): String {
return "Runs all tests for all modules except for disallowed build types and product flavors."
}
override fun getGroup(): String {
return "verification"
}
@TaskAction
fun action() {
println(allowedTestTasks)
// TODO Execute all the allowedTestTasks ./gradlew
}
private fun Test.namedWithAny(disallowedTerms: Set<String>): Boolean {
return disallowedTerms.any { name.contains(it, ignoreCase = true) }
}
}
Then register the custom task:
// /build.gradle
import com.example.TestAllModulesTask
tasks.register("testAllModules", TestAllModulesTask)
Questions
- What would be a modern way to collect all the test tasks and wire them with the custom task? I don’t really like the string comparison here. Filtering by build type and product flavor would be appreciated.
- How do I tell the custom task to actually execute all the test tasks which were collected?