1+ import com.android.build.gradle.BaseExtension
2+
3+ plugins {
4+ jacoco
5+ }
6+
7+ private val fileFilter = mutableSetOf (
8+ " **/R.class" ,
9+ " **/R\$ *.class" ,
10+ " **/*\$ 1*" , // Jacoco can not handle several "$" in class name.
11+ " **/BuildConfig.*" ,
12+ " **/Manifest*.*" ,
13+ " **/*Test*.*" ,
14+ " android/**/*.*" ,
15+ " **/models/**" ,
16+ " **/*\$ Lambda$*.*" , // Jacoco can not handle several "$" in class name.
17+ " **/*\$ inlined$*.*" // Kotlin specific, Jacoco can not handle several "$" in class name.
18+ )
19+
20+
21+ val javaTree = fileTree(" dir" to " ${project.buildDir} /intermediates/javac/debug/classes" , " excludes" to fileFilter)
22+ val kotlinTree = fileTree(" dir" to " ${project.buildDir} /tmp/kotlin-classes/debug" , " excludes" to fileFilter)
23+ private val classDirectoriesTree = fileTree(" ${project.buildDir} " ) {
24+ include(
25+ " **/classes/**/main/**" ,
26+ " **/intermediates/classes/debug/**" ,
27+ " **/intermediates/javac/debug/classes/**" , // Android Gradle Plugin 3.2.x support.
28+ " **/tmp/kotlin-classes/debug/**"
29+ )
30+ exclude(fileFilter)
31+ }
32+
33+ private val sourceDirectoriesTree = fileTree(" ${project.projectDir} " ) {
34+ include(
35+ " src/main/java/**" ,
36+ " src/main/kotlin/**" ,
37+ " src/debug/kotlin/**" ,
38+ " src/release/kotlin/**" ,
39+ )
40+ }
41+
42+ private val executionDataTree = fileTree(project.buildDir) {
43+ include(
44+ " outputs/code_coverage/**/*.ec" ,
45+ " jacoco/jacocoTestReportDebug.exec" ,
46+ " jacoco/testDebugUnitTest.exec" ,
47+ " jacoco/test.exec"
48+ )
49+ }
50+
51+ fun JacocoReportsContainer.reports () {
52+ xml.required.set(false )
53+ html.required.set(true )
54+ html.outputLocation.set(file(" ${buildDir} /reports/jacoco/html" ))
55+ }
56+
57+ fun JacocoCoverageVerification.setDirectories () {
58+ sourceDirectories.setFrom(sourceDirectoriesTree)
59+ classDirectories.setFrom(classDirectoriesTree)
60+ executionData.setFrom(executionDataTree)
61+ }
62+
63+ fun JacocoReport.setDirectories () {
64+ sourceDirectories.setFrom(sourceDirectoriesTree)
65+ classDirectories.setFrom(classDirectoriesTree)
66+ executionData.setFrom(executionDataTree)
67+ }
68+
69+ tasks {
70+ register<JacocoReport >(" jacocoAndroidTestReport" ) {
71+ group = " Verification"
72+ description = " Code coverage report for both Android and Unit tests."
73+ dependsOn(" testDebugUnitTest" /* , "createDebugUnitTestCoverageReport"*/ )
74+ reports {
75+ reports()
76+ }
77+ setDirectories()
78+ }
79+
80+ register<JacocoCoverageVerification >(" jacocoAndroidCoverageVerification" ) {
81+ group = " Verification"
82+ description = " Code coverage verification for Android both Android and Unit tests."
83+ dependsOn(" testDebugUnitTest" , " jacocoAndroidTestReport" /* , "createDebugUnitTestCoverageReport"*/ )
84+ violationRules {
85+ rule {
86+ element = " CLASS"
87+ excludes = listOf (
88+ " **.FactorFacade.Builder" ,
89+ " **.ServiceFacade.Builder" ,
90+ " **.ChallengeFacade.Builder" ,
91+ " **.Task"
92+ )
93+ limit {
94+ minimum = " 0.0" .toBigDecimal()
95+ }
96+ }
97+ }
98+ setDirectories()
99+ }
100+ }
101+
102+ (project as ? ExtensionAware )?.extensions?.configure<BaseExtension >(" android" ) {
103+ buildTypes.forEach { builtType ->
104+ builtType.enableUnitTestCoverage = false
105+ }
106+ }
107+
108+ afterEvaluate {
109+ project.tasks.getByName(" testDebugUnitTest" ).finalizedBy(" jacocoAndroidTestReport" , " jacocoAndroidCoverageVerification" )
110+ }
0 commit comments