|
|
@ -1,5 +1,5 @@
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Copyright 2022 The Android Open Source Project
|
|
|
|
* Copyright 2024 The Android Open Source Project
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
@ -16,8 +16,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
package com.google.samples.apps.nowinandroid
|
|
|
|
package com.google.samples.apps.nowinandroid
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.android.build.api.artifact.ScopedArtifact
|
|
|
|
import com.android.build.api.variant.AndroidComponentsExtension
|
|
|
|
import com.android.build.api.variant.AndroidComponentsExtension
|
|
|
|
|
|
|
|
import com.android.build.api.variant.ScopedArtifacts
|
|
|
|
import org.gradle.api.Project
|
|
|
|
import org.gradle.api.Project
|
|
|
|
|
|
|
|
import org.gradle.api.file.Directory
|
|
|
|
|
|
|
|
import org.gradle.api.file.RegularFile
|
|
|
|
|
|
|
|
import org.gradle.api.provider.ListProperty
|
|
|
|
import org.gradle.api.tasks.testing.Test
|
|
|
|
import org.gradle.api.tasks.testing.Test
|
|
|
|
import org.gradle.kotlin.dsl.configure
|
|
|
|
import org.gradle.kotlin.dsl.configure
|
|
|
|
import org.gradle.kotlin.dsl.register
|
|
|
|
import org.gradle.kotlin.dsl.register
|
|
|
@ -32,13 +37,24 @@ private val coverageExclusions = listOf(
|
|
|
|
"**/R.class",
|
|
|
|
"**/R.class",
|
|
|
|
"**/R\$*.class",
|
|
|
|
"**/R\$*.class",
|
|
|
|
"**/BuildConfig.*",
|
|
|
|
"**/BuildConfig.*",
|
|
|
|
"**/Manifest*.*"
|
|
|
|
"**/Manifest*.*",
|
|
|
|
|
|
|
|
"**/*_Hilt*.class",
|
|
|
|
|
|
|
|
"**/Hilt_*.class",
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
private fun String.capitalize() = replaceFirstChar {
|
|
|
|
private fun String.capitalize() = replaceFirstChar {
|
|
|
|
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString()
|
|
|
|
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Creates a new task that generates a combined coverage report with data from local and
|
|
|
|
|
|
|
|
* instrumented tests.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* `create{variant}CombinedCoverageReport`
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* Note that coverage data must exist before running the task. This allows us to run device
|
|
|
|
|
|
|
|
* tests on CI using a different Github Action or an external device farm.
|
|
|
|
|
|
|
|
*/
|
|
|
|
internal fun Project.configureJacoco(
|
|
|
|
internal fun Project.configureJacoco(
|
|
|
|
androidComponentsExtension: AndroidComponentsExtension<*, *, *>,
|
|
|
|
androidComponentsExtension: AndroidComponentsExtension<*, *, *>,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
@ -46,37 +62,53 @@ internal fun Project.configureJacoco(
|
|
|
|
toolVersion = libs.findVersion("jacoco").get().toString()
|
|
|
|
toolVersion = libs.findVersion("jacoco").get().toString()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
val jacocoTestReport = tasks.create("jacocoTestReport")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
androidComponentsExtension.onVariants { variant ->
|
|
|
|
androidComponentsExtension.onVariants { variant ->
|
|
|
|
val testTaskName = "test${variant.name.capitalize()}UnitTest"
|
|
|
|
val myObjFactory = project.objects
|
|
|
|
val buildDir = layout.buildDirectory.get().asFile
|
|
|
|
val buildDir = layout.buildDirectory.get().asFile
|
|
|
|
val reportTask = tasks.register("jacoco${testTaskName.capitalize()}Report", JacocoReport::class) {
|
|
|
|
val allJars: ListProperty<RegularFile> = myObjFactory.listProperty(RegularFile::class.java)
|
|
|
|
dependsOn(testTaskName)
|
|
|
|
val allDirectories: ListProperty<Directory> = myObjFactory.listProperty(Directory::class.java)
|
|
|
|
|
|
|
|
val reportTask =
|
|
|
|
|
|
|
|
tasks.register("create${variant.name.capitalize()}CombinedCoverageReport", JacocoReport::class) {
|
|
|
|
|
|
|
|
|
|
|
|
reports {
|
|
|
|
classDirectories.setFrom(
|
|
|
|
xml.required.set(true)
|
|
|
|
allJars,
|
|
|
|
html.required.set(true)
|
|
|
|
allDirectories.map { dirs ->
|
|
|
|
}
|
|
|
|
dirs.map { dir ->
|
|
|
|
|
|
|
|
myObjFactory.fileTree().setDir(dir).exclude(coverageExclusions)
|
|
|
|
classDirectories.setFrom(
|
|
|
|
}
|
|
|
|
fileTree("$buildDir/tmp/kotlin-classes/${variant.name}") {
|
|
|
|
}
|
|
|
|
exclude(coverageExclusions)
|
|
|
|
)
|
|
|
|
|
|
|
|
reports {
|
|
|
|
|
|
|
|
xml.required.set(true)
|
|
|
|
|
|
|
|
html.required.set(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sourceDirectories.setFrom(files("$projectDir/src/main/java", "$projectDir/src/main/kotlin"))
|
|
|
|
// TODO: This is missing files in src/debug/, src/prod, src/demo, src/demoDebug...
|
|
|
|
executionData.setFrom(file("$buildDir/jacoco/$testTaskName.exec"))
|
|
|
|
sourceDirectories.setFrom(files("$projectDir/src/main/java", "$projectDir/src/main/kotlin"))
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
executionData.setFrom(
|
|
|
|
|
|
|
|
project.fileTree("$buildDir/outputs/unit_test_code_coverage/${variant.name}UnitTest")
|
|
|
|
|
|
|
|
.matching { include("**/*.exec") },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
project.fileTree("$buildDir/outputs/code_coverage/${variant.name}AndroidTest")
|
|
|
|
|
|
|
|
.matching { include("**/*.ec") }
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
jacocoTestReport.dependsOn(reportTask)
|
|
|
|
variant.artifacts.forScope(ScopedArtifacts.Scope.PROJECT)
|
|
|
|
|
|
|
|
.use(reportTask)
|
|
|
|
|
|
|
|
.toGet(
|
|
|
|
|
|
|
|
ScopedArtifact.CLASSES,
|
|
|
|
|
|
|
|
{ _ -> allJars },
|
|
|
|
|
|
|
|
{ _ -> allDirectories },
|
|
|
|
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tasks.withType<Test>().configureEach {
|
|
|
|
tasks.withType<Test>().configureEach {
|
|
|
|
configure<JacocoTaskExtension> {
|
|
|
|
configure<JacocoTaskExtension> {
|
|
|
|
// Required for JaCoCo + Robolectric
|
|
|
|
// Required for JaCoCo + Robolectric
|
|
|
|
// https://github.com/robolectric/robolectric/issues/2230
|
|
|
|
// https://github.com/robolectric/robolectric/issues/2230
|
|
|
|
// TODO: Consider removing if not we don't add Robolectric
|
|
|
|
|
|
|
|
isIncludeNoLocationClasses = true
|
|
|
|
isIncludeNoLocationClasses = true
|
|
|
|
|
|
|
|
|
|
|
|
// Required for JDK 11 with the above
|
|
|
|
// Required for JDK 11 with the above
|
|
|
|