Skip to content

Instantly share code, notes, and snippets.

@prokash-sarkar
Last active April 6, 2022 18:29
Show Gist options
  • Save prokash-sarkar/38447cba81d9cc313964c3db4e1e714b to your computer and use it in GitHub Desktop.
Save prokash-sarkar/38447cba81d9cc313964c3db4e1e714b to your computer and use it in GitHub Desktop.
private static boolean isAndroidModule(Project project) {
boolean isAndroidLibrary = project.plugins.hasPlugin('com.android.library')
boolean isAndroidApp = project.plugins.hasPlugin('com.android.application')
return isAndroidLibrary || isAndroidApp
}
afterEvaluate { project ->
def projectName = project.name
if (isAndroidModule(project)) setupAndroidReporting()
else setupKotlinReporting()
}
def setupKotlinReporting() {
jacocoTestReport {
dependsOn test
reports {
csv.enabled false // change if needed
xml.enabled false // change if needed
html {
enabled true
destination file("${buildDir}/coverage-report")
}
}
afterEvaluate {
classDirectories.from = files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
// dagger
'**/*_MembersInjector.class',
'**/Dagger*Component.class',
'**/Dagger*Component$Builder.class',
'**/Dagger*Subcomponent*.class',
'**/*Subcomponent$Builder.class',
'**/*Module_*Factory.class',
'**/di/module/*',
'**/*_Factory*.*',
'**/*Module*.*',
'**/*Dagger*.*',
'**/*Hilt*.*',
])
})
}
}
}
def setupAndroidReporting() {
tasks.withType(Test) {
// Whether or not classes without source location should be instrumented
jacoco.includeNoLocationClasses true
}
// Grab all build types and product flavors
def buildTypes = android.buildTypes.collect { type ->
type.name
}
def productFlavors = android.productFlavors.collect { flavor ->
flavor.name
}
// When no product flavors defined, use empty
if (!productFlavors) productFlavors.add('')
productFlavors.each { productFlavorName ->
buildTypes.each { buildTypeName ->
def sourceName, sourcePath
if (!productFlavorName) {
sourceName = sourcePath = "${buildTypeName}"
} else {
sourceName = "${productFlavorName}${buildTypeName.capitalize()}"
sourcePath = "${productFlavorName}/${buildTypeName}"
}
def testTaskName = "test${sourceName.capitalize()}UnitTest"
System.out.println("Task -> $testTaskName")
// Create coverage task of form 'testFlavorTypeCoverage' depending on 'testFlavorTypeUnitTest'
task "${testTaskName}Coverage"(type: JacocoReport, dependsOn: "$testTaskName") {
group = "Reporting"
description = "Generate Jacoco coverage reports on the ${sourceName.capitalize()} build."
def fileFilter = [
// data binding
'android/databinding/**/*.class',
'**/android/databinding/*Binding.class',
'**/android/databinding/*',
'**/androidx/databinding/*',
'**/BR.*',
// android
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*Test*.*',
'android/**/*.*',
// dagger
'**/*_MembersInjector.class',
'**/Dagger*Component.class',
'**/Dagger*Component$Builder.class',
'**/Dagger*Subcomponent*.class',
'**/*Subcomponent$Builder.class',
'**/*Module_*Factory.class',
'**/di/module/*',
'**/*_Factory*.*',
'**/*Module*.*',
'**/*Dagger*.*',
'**/*Hilt*.*',
// kotlin
'**/*MapperImpl*.*',
'**/*$ViewInjector*.*',
'**/*$ViewBinder*.*',
'**/BuildConfig.*',
'**/*Component*.*',
'**/*BR*.*',
'**/Manifest*.*',
'**/*$Lambda$*.*',
'**/*Companion*.*',
'**/*Module*.*',
'**/*Dagger*.*',
'**/*Hilt*.*',
'**/*MembersInjector*.*',
'**/*_MembersInjector.class',
'**/*_Factory*.*',
'**/*_Provide*Factory*.*',
'**/*Extensions*.*',
// sealed and data classes
'**/*$Result.*',
'**/*$Result$*.*',
// adapters generated by moshi
'**/*JsonAdapter.*',
]
def javaTree = fileTree(dir: "${project.buildDir}/intermediates/javac/$sourceName/classes", excludes: fileFilter)
def kotlinTree = fileTree(dir: "${project.buildDir}/tmp/kotlin-classes/$sourceName", excludes: fileFilter)
classDirectories.from = files([javaTree], [kotlinTree])
executionData.from = files("${project.buildDir}/jacoco/${testTaskName}.exec")
def coverageSourceDirs = ["src/main/java",
"src/$productFlavorName/java",
"src/$buildTypeName/java"]
sourceDirectories.setFrom(files(coverageSourceDirs))
additionalSourceDirs.setFrom(files(coverageSourceDirs))
reports {
csv.enabled false // change if needed
xml.enabled false // change if needed
html {
enabled true
destination file("${buildDir}/coverage-report")
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment