Improve Jacoco setup.

This commit is contained in:
Yahor Berdnikau 2018-10-07 20:45:20 +02:00
parent 21bcb5429a
commit 3371b4025d
4 changed files with 83 additions and 57 deletions

View File

@ -1,5 +1,10 @@
apply from: bootstrap.kotlinModule apply from: bootstrap.kotlinModule
ext {
jacocoExclude = [
'**/domain/**'
]
}
dependencies { dependencies {
api other.semver api other.semver
} }

View File

@ -4,72 +4,89 @@ jacoco {
toolVersion(versions.jacoco) toolVersion(versions.jacoco)
} }
task jacocoMergeReports(type: JacocoMerge) { def mergedJacocoExec = file("${project.buildDir}/jacoco/jacocoMerged.exec")
tasks.create(name: 'jacocoMergeReports', type: JacocoMerge) {
group = "Reporting" group = "Reporting"
description = "Merge all jacoco reports from projects into one." description = "Merge all jacoco reports from projects into one."
List<File> jacocoFiles = new ArrayList<>() ListProperty<File> jacocoFiles = project.objects.listProperty(File.class)
project.subprojects { subproject -> project.subprojects { subproject ->
File commonModuleReport = new File(subproject.buildDir, "/jacoco/test.exec") subproject.plugins.withId("jacoco") {
if (commonModuleReport.exists()) jacocoFiles.add(commonModuleReport) project.logger.info("${subproject.name} has Jacoco plugin applied")
File androidModuleReport = new File(subproject.buildDir, "/jacoco/testDebugUnitTest.exec") subproject.tasks.withType(Test) { task ->
if (androidModuleReport.exists()) jacocoFiles.add(androidModuleReport) File destFile = task.extensions.getByType(JacocoTaskExtension.class).destinationFile
if (destFile.exists() && !task.name.contains("Release")) {
jacocoFiles.add(destFile)
}
}
}
} }
executionData(jacocoFiles.toArray())
destinationFile(file("${project.buildDir}/jacoco/jacoco.exec")) executionData(jacocoFiles)
destinationFile(mergedJacocoExec)
} }
def createJacocoFullReportTask() { tasks.create(name: 'jacocoFullReport', type: JacocoReport, dependsOn: 'jacocoMergeReports') {
tasks.create(name: 'jacocoFullReport', type: JacocoReport, dependsOn: 'jacocoMergeReports') { group = "Reporting"
group = "Reporting" description = "Generate full Jacoco coverage report including all modules."
description = "Generate full Jacoco coverage report including all modules."
List<FileTree> classFileTreeList = new ArrayList<>() classDirectories = files()
List<FileTree> sourceFileTreeList = new ArrayList<>() sourceDirectories = files()
executionData = files()
reports {
xml.enabled = true
html.enabled = true
csv.enabled = false
}
// Always run merging, as all input calculation is done in doFirst {}
outputs.upToDateWhen { false }
// Task will run anyway even if initial inputs are empty
onlyIf = { true }
doFirst {
project.subprojects { subproject -> project.subprojects { subproject ->
if (subproject.plugins.hasPlugin("kotlin-android") && subproject.plugins.withId("jacoco") {
subproject.hasProperty("jacocoExclude")) { project.logger.info("${subproject.name} has Jacoco plugin applied")
classFileTreeList.add( subproject.plugins.withId("kotlin-android") {
fileTree( project.logger.warn("${subproject.name} is android project")
dir: "${subproject.buildDir}/tmp/kotlin-classes/debug", def mainSources = subproject.extensions.findByName("android").sourceSets['main']
excludes: subproject.jacocoExclude project.logger.warn("Android sources: ${mainSources.java.srcDirs}")
) mainSources.java.srcDirs.forEach {
) additionalSourceDirs(it)
sourceFileTreeList.add( }
subproject.extensions.getByName('android').sourceSets.main.java.sourceFiles project.logger.warn("Subproject exclude: ${subproject.jacocoExclude}")
) additionalClassDirs(fileTree(
} else if (subproject.hasProperty("jacocoExclude")) { dir: "${subproject.buildDir}/tmp/kotlin-classes/debug",
classFileTreeList.add( excludes: subproject.jacocoExclude
fileTree( ))
dir: "${subproject.buildDir}/classes/kotlin/main", }
excludes: subproject.jacocoExclude subproject.plugins.withId("kotlin") { plugin ->
) project.logger.warn("${subproject.name} is common kotlin project")
) SourceDirectorySet mainSources = subproject.extensions.getByName("kotlin")
sourceFileTreeList.add(subproject.sourceSets.main.getAllSource()) .sourceSets[SourceSet.MAIN_SOURCE_SET_NAME]
.kotlin
mainSources.srcDirs.forEach {
project.logger.debug("Adding sources: $it")
additionalSourceDirs(it)
}
project.logger.warn("Subproject exclude: ${subproject.jacocoExclude}")
additionalClassDirs(fileTree(
dir: "${subproject.buildDir}/classes/kotlin/main",
excludes: subproject.jacocoExclude
))
}
subproject.tasks.withType(Test) { task ->
File destFile = task.extensions.getByType(JacocoTaskExtension.class).destinationFile
if (destFile.exists() && !task.name.contains("Release")) {
project.logger.info("Adding execution data: $destFile")
executionData(destFile)
}
}
} }
} }
classDirectories = files(classFileTreeList.toArray())
sourceDirectories = files(sourceFileTreeList.toArray())
executionData = files("${buildDir}/jacoco/jacoco.exec")
reports {
xml.enabled = true
html.enabled = true
csv.enabled = false
}
} }
} }
// We need to wait to all subprojects configuration finish or we don't get sources and exclusions
def subprojectsCount = allprojects.size()
allprojects {
afterEvaluate { subproject ->
subprojectsCount--
if (subprojectsCount == 0) {
apply {
createJacocoFullReportTask()
}
}
}
}

View File

@ -55,7 +55,7 @@ test {
} }
} }
task("ciTest", dependsOn: "test") { tasks.create(name: "ciTest", dependsOn: "test") {
group = "Verification" group = "Verification"
description = "Special task for CI that calls all tests in pure kotlin modules" description = "Special task for CI that calls all tests in pure kotlin modules"
} }

View File

@ -77,6 +77,10 @@ dependencies {
testImplementation testing.kluent testImplementation testing.kluent
} }
jacoco {
toolVersion(versions.jacoco)
}
// Excluding all java classes and stuff that should not be covered // Excluding all java classes and stuff that should not be covered
ext { ext {
jacocoExclude = [ jacocoExclude = [