Skip to content

Instantly share code, notes, and snippets.

@cesarioputera
Created November 4, 2019 10:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cesarioputera/859456a3846776ca82dd1904180ce964 to your computer and use it in GitHub Desktop.
Save cesarioputera/859456a3846776ca82dd1904180ce964 to your computer and use it in GitHub Desktop.
apply from: "../jacoco.gradle"
def debugTree = fileTree(dir: "${buildDir}/intermediates/packaged-classes/flavorUnsigned", includes: includeFileFilter, excludes: excludeFileFilter)
def kotlinDebugTree = fileTree(dir: "${buildDir}/tmp/kotlin-classes/flavorUnsignedDebug", includes: includeFileFilter, excludes: excludeFileFilter)
def mainSrc = "${project.projectDir}/src/main/java"
task jacocoTestReport(type: JacocoReport, dependsOn: ['testFlavorUnsignedDebugUnitTest', 'assembleDebug']) {
reports {
xml.enabled = true
html.enabled = true
}
getSourceDirectories().setFrom(files([mainSrc]))
getClassDirectories().setFrom(files([debugTree], [kotlinDebugTree]))
getExecutionData().setFrom(fileTree(dir: "$buildDir", includes: [
"jacoco/testFlavorUnsignedDebugUnitTest.exec",
]))
}
check.dependsOn jacocoTestReport
apply plugin: "jacoco"
ext.excludeFileFilter = [
//ExcludeFiles
]
jacoco {
toolVersion = "0.8.2"
}
ext {
limits = [
'instruction': 50
]
}
ext.includeFileFilter = [
//IncludedFiles
]
android {
testOptions {
unitTests.all {
jacoco {
includeNoLocationClasses = true
}
}
unitTests.returnDefaultValues = true
}
}
apply from: '../sonarqube.gradle'
sonarqube {
//read the flavor from properties.
def flavorName = "flavorUnsigned"
def variant = "debug"
androidVariant flavorName + variant.capitalize()
properties {
def libraries = project.android.sdkDirectory.getPath() + "/platforms/android-28/android.jar" + ",build/intermediates/packaged-classes/**/classes.jar"
property "sonar.projectVersion", app_version
property 'sonar.binaries', "build/intermediates/packaged-classes/$flavorName,build/tmp/kotlin-classes/$androidVariant"
property "sonar.libraries", libraries
property 'sonar.java.binaries', "build/intermediates/packaged-classes/$flavorName,build/tmp/kotlin-classes/$androidVariant"
property "sonar.java.libraries", libraries
property 'sonar.java.test.binaries', "build/intermediates/packaged-classes/$flavorName,build/tmp/kotlin-classes/$androidVariant"
property "sonar.java.test.libraries", libraries
property 'sonar.junit.reportsPaths', "build/test-results/test${androidVariant.capitalize()}UnitTest"
property 'sonar.jacoco.reportPaths', "build/jacoco/test${androidVariant.capitalize()}UnitTest.exec"
}
}
apply plugin: 'org.sonarqube'
sonarqube {
properties {
property "sonar.projectVersion", app_version
property "sonar.sourceEncoding", "UTF-8"
property "sonar.sources", "src/main/java"
property "sonar.tests", "src/test/java"
property "sonar.dynamicAnalysis", "reuseReports"
property 'sonar.java.coveragePlugin', 'jacoco'
property 'sonar.coverage.exclusions', excludeFileFilter.join(',')
property "sonar.scm.provider", "git"
}
}
@anton46
Copy link

anton46 commented Nov 4, 2019

  1. Missing jacoco default report config
android {
...
 buildTypes {
        debug {
            testCoverageEnabled true
        }
    }
...
}
  1. The dependsOn missing some tasks from each modules :<module-name>:testDebugUnitTest

Sample config for modularization :

def fileFilter = []

task testDebugUnitTestCoverage(type: JacocoReport) {
    group = 'Reporting'
    description = "Generate Jacoco coverage reports for the debug build. Only unit tests."

    //Make sure that tests from all modules are run before coverage report
    dependsOn ":app:testDebugUnitTest"
    dependsOn ":features:feature1:testDebugUnitTest"
    dependsOn ":features:feature2:testDebugUnitTest"
    dependsOn ":features:feature3:testDebugUnitTest"

    classDirectories = files([
            fileTree(dir: "$project.rootDir/app/build/intermediates/javac/debug", excludes: fileFilter),
            fileTree(dir: "$project.rootDir/features/feature1/build/intermediates/javac/debug", excludes: fileFilter),
            fileTree(dir: "$project.rootDir/features/feature2/build/intermediates/javac/debug", excludes: fileFilter),
            fileTree(dir: "$project.rootDir/features/feature3/build/intermediates/javac/debug", excludes: fileFilter),
    ])
    def coverageSourceDirs = [
            "$project.rootDir/app/src/main/java",
            "$project.rootDir/features/base/src/main/java",
            "$project.rootDir/features/repository/src/main/java",
            "$project.rootDir/features/repositories/src/main/java",
    ]
    additionalSourceDirs = files(coverageSourceDirs)
    sourceDirectories = files(coverageSourceDirs)
    executionData = fileTree(dir: project.rootDir, includes: [
            'app/build/jacoco/testDebugUnitTest.exec',
            'features/feature1/build/jacoco/testDebugUnitTest.exec',
            'features/feature2/build/jacoco/testDebugUnitTest.exec',
            'features/feature3/build/jacoco/testDebugUnitTest.exec',
    ])

    reports {
        xml.enabled = true
        html.enabled = true
    }
}

@cesarioputera
Copy link
Author

Hi @anton46,

for suggestion #2:
I have 1 jacoco configuration for each module, I used common jacoco-lib.gradle and include it in each features' build.gradle. Which one is better? :D
because of my configuration, I don't think the dependsOn has effect for this.

@anton46
Copy link

anton46 commented Nov 4, 2019

Thats might be the problem why sonar couldnt collect the report. You need to combine all together in one executions

@esafirm
Copy link

esafirm commented Nov 4, 2019

Kalo aku sekarang cuma pake satu file jacoco.gradle yang akan di include di root gradle

Disitu nanti filter module mana aja yang mau aku include ke jacoco (karena ada beberapa module yg generated)

Something like this:

final coveredModules = subprojects.findAll { IsShouldBeCovered }
configure(coveredModules) {
  // And now we define our jacoco task that depends on our test
  task jacocoReport(type: JacocoReport, dependsOn: 'testDebugUnitTest') {
  }
}

After this you can define your whole project coverage report

task jacocoMarketpalceApp(type: JacocoReport) {
  dependsOn(projects.jacocoReport)

final source = files(projects.jacocoReport.sourceDirectories)

    additionalSourceDirs.setFrom source
    sourceDirectories.setFrom source

    classDirectories.setFrom files(projects.jacocoReport.classDirectories)
    executionData.setFrom files(projects.jacocoReport.executionData)

    reports {
       // config your aggregated reports here
    }
} 

@cesarioputera
Copy link
Author

oh one more thing, how about the sonar's setting? In my case did the same thing like jacoco's setting, create 1 sonar-lib.gradle and include it in each build.gradle

@esafirm
Copy link

esafirm commented Nov 4, 2019

oh one more thing, how about the sonar's setting? In my case did the same thing like jacoco's setting, create 1 sonar-lib.gradle and include it in each build.gradle

I haven't tried it yet, but i think the principle is the same.
Also, you could configure it to apply your gradle files to all your subprojects

// in your root gradle
subProjects {
   apply from : sonarqube.gradle
}

@cesarioputera
Copy link
Author

Hi @anton46 @esafirm
The issue is resolved now
Thank you for the suggestion
After did the changes (implement the suggested approach), the problem is the path and there are some deprecated properties in sonar

sonarqube {
    //read the flavor from properties.
    def flavorName = "flavorUnsigned"
    def variant = "debug"
    androidVariant flavorName + variant.capitalize() --------> //outside

    properties {
        ...
        property 'sonar.binaries', "build/tmp/kotlin-classes/$androidVariant" --------> //inside
        property "sonar.libraries", libraries
        ...
        property 'sonar.junit.reportsPaths', "build/test-results/test${androidVariant.capitalize()}UnitTest"
        property 'sonar.jacoco.reportPaths', "build/jacoco/test${androidVariant.capitalize()}UnitTest.exec"
    }
}
  1. Path issue: the androidVariant inside the propery{} is different with the outside androidVariant
  2. Deprecated property: sonar.jacoco.reportPaths has been deprecated and changed to sonar.coverage.jacoco.xmlReportPaths

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment