Skip to content

Instantly share code, notes, and snippets.

@Piasy
Created August 23, 2015 08:41
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Piasy/4d658ebcf9b9a6af29ad to your computer and use it in GitHub Desktop.
Save Piasy/4d658ebcf9b9a6af29ad to your computer and use it in GitHub Desktop.
Android Gradle build script that create jacocoReport task for all sub projects, with some customization
/**
* List of modules that don't require Jacoco
*/
def ignoredByJacoco = [
'presentation'
]
/**
* module class dirs
* */
def moduleClassDirs = [
'common' : 'build/classes',
'common-android': 'build/intermediates/classes/debug',
'model' : 'build/intermediates/classes/debug',
'presentation' : 'build/intermediates/classes/debug'
]
/**
* module jacoco exec
* */
def moduleJacocoExec = [
'common' : 'build/jacoco/test.exec',
'common-android': 'build/jacoco/testDebugUnitTest.exec',
'model' : 'build/jacoco/testDebugUnitTest.exec',
'presentation' : 'build/jacoco/testDebugUnitTest.exec'
]
/**
* module excludes
* */
def moduleExcludes = [
'common' : [
'**/R*.class',
'**/BuildConfig*'
],
'common-android': [
'**/R*.class',
'**/BuildConfig*'
],
'model' : [
'**/R*.class',
'**/BuildConfig*'
],
'presentation' : [
'**/R*.class',
'**/BuildConfig*'
]
]
/**
* Apply additional build steps to sub-projects
*/
subprojects { prj ->
// Apply Jacoco only if the project is not in the ignore list
if (!ignoredByJacoco.contains(prj.name)) {
apply plugin: 'jacoco'
jacoco {
version rootProject.ext.jacocoVersion
}
task jacocoReport(type: JacocoReport, dependsOn: 'test') {
group = 'Reporting'
description = 'Generate Jacoco coverage reports after running tests.'
reports {
xml.enabled = true
html.enabled = true
}
classDirectories = fileTree(
dir: moduleClassDirs[prj.name],
excludes: moduleExcludes[prj.name]
)
sourceDirectories = files('src/main/java')
executionData = files(moduleJacocoExec[prj.name])
doFirst {
renameClasses(prj.name + File.separator + moduleClassDirs[prj.name])
}
}
}
}
apply plugin: 'jacoco'
jacoco {
toolVersion rootProject.ext.jacocoVersion
}
/**
* Root task that generates an aggregated Jacoco test coverage report for all sub-projects
*/
task jacocoFullReport(type: JacocoReport, group: 'Coverage reports') {
group = 'Reporting'
description = 'Generates an aggregate report from all subprojects'
// Get list of projects which should be included in the report
def projects = new ArrayList()
subprojects.each { prj ->
if (!ignoredByJacoco.contains(prj.name)) {
projects.add(prj)
}
}
//noinspection GrUnresolvedAccess
dependsOn(projects.jacocoReport)
additionalSourceDirs = generateSourceFiles(projects)
sourceDirectories = generateSourceFiles(projects)
classDirectories = generateClassDirs(projects, moduleClassDirs, moduleExcludes)
executionData = files(projects.jacocoReport.executionData)
reports {
html {
enabled true
destination 'build/reports/jacoco/full'
}
xml {
enabled true
destination 'build/reports/jacoco/full/jacocoFullReport.xml'
}
}
doFirst {
//noinspection GroovyAssignabilityCheck
executionData = files(executionData.findAll { it.exists() })
}
}
/**
* Generate a FileCollection of all projects source files
*/
FileCollection generateSourceFiles(Collection projects) {
def dirs = []
projects.each { prj ->
dirs.add("${prj.name}/src/main/java")
}
return files(dirs)
}
/**
* Generate a FileCollection of all projects class files
*/
FileCollection generateClassDirs(Collection projects, moduleClassDirs, moduleExcludes) {
def tree = fileTree('directory does not exists') // I know it's ugly :)
projects.each { prj ->
//noinspection GrReassignedInClosureLocalVar
tree += fileTree(
dir: "${prj.name}/${moduleClassDirs[prj.name]}",
excludes: moduleExcludes[prj.name]
)
}
return tree
}
List<File> listDirRecursive(File rootPath) {
List<File> result = new ArrayList<>()
List<File> children = rootPath.listFiles()
children.each { file ->
if (file.isFile()) {
result.add(file)
} else if (file.isDirectory()) {
result.addAll(listDirRecursive(file))
}
}
return result
}
void renameClasses(String rootPath) {
List<File> classes = listDirRecursive(file(rootPath))
classes.each { file ->
if (file.name.contains('$$')) {
file.renameTo(file.path.replace('$$', '$'))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment