I have an android project. I want to introduce findbugs in my project as a gradle plugin. I tried to edit the project's build.gradle as below.
buildscript {
repositories {
mavenCentral()
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0+'
classpath 'io.fabric.tools:gradle:1.+'
}
}
apply plugin: "java"
apply plugin: "findbugs"
findbugs {
toolVersion = "2.0.1"
sourceSets = [sourceSets.main]
ignoreFailures = false
reportsDir = file("$project.buildDir/findbugsReports")
effort = "max"
reportLevel = "high"
includeFilter = file("$rootProject.projectDir/config/findbugs/includeFilter.xml")
excludeFilter = file("$rootProject.projectDir/config/findbugs/excludeFilter.xml")
}
Is this plugin correct?
Does anything neeed to be added or removed?
Now what should I do to get the results of this findbugs check?
What gradle command should I use?
Just place this in your modules build.gradle.
apply plugin: 'findbugs'
task customFindbugs(type: FindBugs) {
ignoreFailures = false
effort = "max"
reportLevel = "low"
classes = files("$project.buildDir/intermediates/classes")
// Use this only if you want exclude some errors
excludeFilter = file("$rootProject.rootDir/config/findbugs/exclude.xml")
source = fileTree('src/main/java/')
classpath = files()
reports {
xml.enabled = false
xml.withMessages = true
html.enabled = !xml.isEnabled()
xml.destination "$project.buildDir/outputs/findbugs/findbugs-output.xml"
html.destination "$project.buildDir/outputs/findbugs/findbugs-output.html"
}
}
build.dependsOn customFindbugs
Then after changing directory to your project path from command line, use
./gradlew build
The error report will be in $project.buildDir/outputs/findbugs/findbugs-output.html
I modified a little bit Nevin Raj Victor's answer.
This version generates a findbug task for each build variant, and (more importantly) it correctly creates dependencies on their respective compilation tasks. Indeed, findbugs requires the code to be compiled before it can be analyzed.
// findbug tasks for each variant
apply plugin: 'findbugs'
android.applicationVariants.all { variant ->
task("findbugs${variant.name.capitalize()}", type: FindBugs) {
description "Analyze ${variant.name} code with the findbugs tool"
group "Verification"
ignoreFailures = true
effort = "default"
reportLevel = "medium"
classes = files("$project.buildDir/intermediates/classes/${variant.dirName}")
excludeFilter = file("$rootProject.rootDir/findbugs/findbugs-filter.xml")
source = variant.javaCompile.source
classpath = variant.javaCompile.classpath
reports {
// Only one of HTML or XML can be turned on at the same time
html.enabled = true
xml.enabled = !html.enabled
xml.withMessages = true
html.destination = "$project.buildDir/outputs/findbugs/findbugs-${variant.name}-output.html"
xml.destination = "$project.buildDir/outputs/findbugs/findbugs-${variant.name}-output.xml"
}
dependsOn "compile${variant.name.capitalize()}JavaWithJavac"
}
}
After this, you can run
./gradlew findbugsDebug
./gradlew findbugsRelease
Or other findbugs tasks on different variants, depending on your configuration.
Please take a look at this project https://github.com/Piasy/AndroidCodeQualityConfig.
This project including lint, pmd, findbugs, checkstyle, jacoco code coverage.And support project with submodules.
I see some problems with your configuration:
instead of 2.0.1 version use latest 3.0.1
set reportLevel to low instead of high to report all the violations
for the first analysis you don't need to configure any includeFilter or excludeFilter - these are only whitelist and blacklists of checks if you need some customization
To run analysis just invoke gradle findbugsMain. Results should be visible in the output.
Related
How do I set up SpotBugs for Android?
I tried following the official documentation and that of the gradle plugin, but the setup for Android is incomplete and confusing, and didn't work.
I tried the following setup.
build.gradle (project):
buildscript {
repositories {
// ...
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
// ...
classpath "gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:1.6.4"
}
}
build.gradle (app):
//...
apply plugin: "com.github.spotbugs"
android {
// ...
sourceSets {
main {
java.srcDirs = ['src/main/java']
}
}
}
// ...
spotbugs {
toolVersion = "3.1.3"
ignoreFailures = true
reportsDir = file("$project.buildDir/findbugsReports")
effort = "max"
reportLevel = "high"
}
tasks.withType(com.github.spotbugs.SpotBugsTask) {
// What do I need to do here?
}
I tried running it with ./gradlew spotbugsMain, but the gradle task is missing.
Am I supposed to add the task manually? How do I do that?
Could you show me an example of a minimal working setup for an Android project?
I made some tests on my side and I manage to make it work like this :
1) Move the sourceSets declaration outside the android block. Leave it empty, it's just for the spotbugsMain task generation, it won't impact the global Android build.
android {
// ...
}
sourceSets {
main {
java.srcDirs = []
}
}
2) Keep your spotbugs block and configure the SpotBugsTask tasks like this :
tasks.withType(com.github.spotbugs.SpotBugsTask) {
classes = files("$projectDir.absolutePath/build/intermediates/classes/debug")
source = fileTree('src/main/java')
}
It will generate reports in app/build/findbugsReports
Important :
It only works with the ./gradlew build command, ./gradlew spotbugsMain won't work as the project must be built before
You can fix that adding an assemble dependency :
tasks.withType(com.github.spotbugs.SpotBugsTask) {
dependsOn 'assemble'
classes = files("$projectDir.absolutePath/build/intermediates/classes/debug")
source = fileTree('src/main/java')
}
Following on from ToYonos answer (9 October 2018); Use this for Android Studio 3.4 and above:
project/build.gradle
buildscript {
repositories {
google()
jcenter()
maven {
url 'https:// maven url 1'
}
maven {
url "https://plugins.gradle.org/m2/" // Add this, for SpotBugs
}
}
dependencies {
classpath '...'
// If you're using gradle 6.x, add this to use SpotBugs app version 4.0.2
classpath "gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:4.3.0"
// If you're using gradle 4.x or 5.x, add this to use SpotBugs app version 3.1.2
classpath "com.github.spotbugs:spotbugs-gradle-plugin:2.0.1"
}
}
project/app/build.gradle
apply plugin: 'com.android.application'
apply plugin: '...'
apply plugin: "com.github.spotbugs" // <- Add this
dependencies {
...
}
// This block is only needed for gradle 4/5 only.
// It's for SpotBugs to create a 'spotbugsMain' gradle task.
sourceSets {
main {
java.srcDirs = []
}
}
spotbugs {
ignoreFailures = true
reportsDir = file("$project.buildDir/SpotBugsReports")
effort = "max"
reportLevel = "high"
}
// Note: gradle 4/5 should use "com.github.spotbugs.SpotBugsTask"
tasks.withType(com.github.spotbugs.snom.SpotBugsTask) {
dependsOn 'assembleDebug'
classes = files("$project.buildDir/intermediates/javac") // Important to use this path
excludeFilter = file("$project/spot-bugs-exclude.xml") // Optional - Explained below
source = fileTree('src/main/java') // Only needed on gradle 4/5
reports {
// Enable HTML report only
html.enabled = true
xml.enabled = false
}
}
You can generate a report for your debug build by running the gradle task:
For gradle 6.x: ./gradlew spotbugsDebug
For gradle 5 or 4: ./gradlew spotbugsMain
It's important to use classes = files("$project.buildDir/intermediates/javac") , otherwise you'll get an error "java.io.IOException: No files to analyze could be opened" -- see Findbugs fails with "java.io.IOException: No files to analyze could be opened"
You'll also need to enable the HTML report and disable XML report, to see a human-readable format.
ignoreFailures = true is optional. When SpotBugs detects a code warning, by default it will end with "BUILD FAILED" + a report file. Setting ignoreFailures = true means the gradle task will end with "BUILD SUCCESSFUL" + a report file.
To exclude some generated classes from the analysis, setup an excludeFilter. For a sample exclude file, check here or here (same as findbugs-exclude.xml)
More information and tutorial here: https://mikedemaso.com/tech/2020-06-10-spotbugs-gradle-plugin-android/
I've been working on adding SpotBugs to the android project I'm currently working on. I managed to get it working but I'm not overly thrilled of the way it's set up. For now the configuration resides inside my app/build.gradle file, which makes the file less manageable.
I was wondering if there's an expert on SpotBugs/Gradle who knows a way to pull the configuration out into a separate file.
Here's my app/build.gradle (boilerplate removed):
buildscript {
repositories {
...
}
dependencies {
classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.2.2'
classpath 'io.fabric.tools:gradle:1.25.4'
classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:$dokka_version"
}
}
plugins {
id 'com.gladed.androidgitversion' version '0.4.3'
id "com.github.spotbugs" version "1.6.2"
}
...
apply plugin: 'com.github.spotbugs'
apply from: '../config/quality/quality.gradle'
apply from: '../app/jacoco.gradle'
apply from: '../app/ktlint.gradle'
apply from: '../app/androidgit.gradle'
...
spotbugs {
toolVersion = '3.1.3'
ignoreFailures = false
effort = "min"
// This selects what level of bugs to report: low means low priority issues will be reported
// (in addition to medium+high), which corresponds to warning about everything.
// TODO: boost this to low once low priority issues are fixed.
reportLevel = "medium"
excludeFilter = new File("$project.rootDir/config/quality/spotbugs/android-exclude-filter.xml")
}
task spotbugs(type: com.github.spotbugs.SpotBugsTask, dependsOn: 'assemble', group: 'verification') {
classes = files("$projectDir.absolutePath/build/intermediates/app_classes/debug")
source = fileTree('src/main/java')
// Only one report format is supported. Html is easier to read, so let's use that
// (xml is the one that's enabled by default).
reports {
xml.enabled = false
html.enabled = true
}
classpath = files()
}
EDIT
Whenever I'm trying to separate SpotBugs from my app/build.gradle I run into the following error:
Could not get unknown property 'SpotBugsTask' for project ':app' of type org.gradle.api.Project.
Here's my gradle file:
apply plugin: 'com.github.spotbugs'
dependencies {
checkstyle 'com.puppycrawl.tools:checkstyle:8.11'
spotbugs "gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:1.6.2"
// spotbugs configurations.spotbugsPlugins.dependencies
// spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.8.0'
}
def qualityConfigDir = "$project.rootDir/config/quality";
def reportsDir = "$project.buildDir/reports"
check.dependsOn 'checkstyle'
task checkstyle(type: Checkstyle, group: 'Verification', description: 'Runs code style checks') {
configFile file("$qualityConfigDir/checkstyle/checkstyle-config.xml")
source 'src/main/java'
include '**/*.java'
exclude '**/model/**'
exclude '**/AppLogger.java'
reports {
xml.enabled = true
xml {
destination file("$reportsDir/checkstyle/checkstyle.xml")
}
}
classpath = files()
}
spotbugs {
toolVersion = '3.1.3'
ignoreFailures = false
effort = "min"
// This selects what level of bugs to report: low means low priority issues will be reported
// (in addition to medium+high), which corresponds to warning about everything.
// TODO: boost this to low once low priority issues are fixed.
reportLevel = "medium"
excludeFilter = new File("$project.rootDir/config/quality/spotbugs/android-exclude-filter.xml")
}
task spotbugs(type: SpotBugsTask, dependsOn: 'assemble', group: 'verification') {
classes = files("$projectDir.absolutePath/build/intermediates/app_classes/debug")
source = fileTree('src/main/java')
// Only one report format is supported. Html is easier to read, so let's use that
// (xml is the one that's enabled by default).
reports {
xml.enabled = false
html.enabled = true
}
classpath = files()
}
Finally managed to find a solution.
I had to add the following to the section where I apply all the plugins in my app/build.gradle file:
project.extensions.extraProperties.set('SpotBugsTask', com.github.spotbugs.SpotBugsTask)
So it ended up looking like this:
buildscript {
repositories {
mavenCentral()
jcenter()
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.2.2'
classpath 'io.fabric.tools:gradle:1.25.4'
classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:$dokka_version"
}
}
plugins {
id 'com.gladed.androidgitversion' version '0.4.3'
id "com.github.spotbugs" version "1.6.2"
}
// Workaround to be able to access SpotBugsTask from external gradle script.
// More info: https://discuss.gradle.org/t/buildscript-dependencies-in-external-script/23243
project.extensions.extraProperties.set('SpotBugsTask', com.github.spotbugs.SpotBugsTask)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'org.jetbrains.dokka-android'
apply plugin: 'io.fabric'
apply plugin: 'spoon'
apply from: '../app/checkstyle.gradle'
apply from: '../app/jacoco.gradle'
apply from: '../app/ktlint.gradle'
apply from: '../app/androidgit.gradle'
apply from: '../app/spotbugs.gradle'
android {
...
My spotbugs.gradle file:
dependencies {
spotbugs configurations.spotbugsPlugins.dependencies
spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.8.0'
}
def qualityConfigDir = "$project.rootDir/config/quality"
def reportsDir = "$project.buildDir/reports"
spotbugs {
toolVersion = "$spotbugs_version"
ignoreFailures = false
effort = "min"
// This selects what level of bugs to report: low means low priority issues will be reported
// (in addition to medium+high), which corresponds to warning about everything.
// TODO: boost this to low once low priority issues are fixed.
reportLevel = "medium"
excludeFilter = new File("$qualityConfigDir/config/quality/spotbugs/android-exclude-filter.xml")
}
tasks.register("spotbugs", SpotBugsTask) {
dependsOn 'assemble'
group = "verification"
classes = files("$projectDir.absolutePath/build/intermediates/app_classes/debug")
source = fileTree('src/main/java')
// Only one report format is supported. Html is easier to read, so let's use that
// (xml is the one that's enabled by default).
reports {
xml.enabled = true
xml {
destination file("$reportsDir/spotbugs/spotbugs.xml")
}
html.enabled = true
}
classpath = files()
}
For anyone stumbling across this thread, and not satisfied with the above answer (you should question anytime you see "this works" without a "because ..."), note that if you're using an external buildscript file like the OP, and trying to configure the tasks, the real problem is that the script plugin ClassLoader is isolated from the project buildscript ClassLoader, the java.lang.Class instances representing the type com.github.spotbugs.SpotBugsTask are different, thus thewithType call doesn't match anything.
See gradle-native#742 and gradle#1262 for details, and some solutions to make it work.
This question already has answers here:
JaCoCo doesn't work with Robolectric tests
(6 answers)
Closed 5 years ago.
On my android project jacoco doesn't include the robolectic tests. I can get the android espresso and junit test coverage with jacoco without any issues.
I did see other questions about this issue and all the answers is to upgrade jacoco version. I'm using the latest jacoco version 0.7.9
This is my project main build.gradle
buildscript {
dependencies {
classpath 'org.jacoco:org.jacoco.core:0.7.9'
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6-rc1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
App module build gradle.
apply plugin: 'jacoco'
android {
testOptions {
unitTests.all {
jacoco {
includeNoLocationClasses = true
}
includeAndroidResources = true
}
}
}
I solve that problem with creating a separate task for jacoco in gradle.
First off all you need to add jacoco plugin.
apply plugin: "jacoco"
I didn't add any dependencies as you do on the code snippet above. Just add plugin.
Then add testCoverageEnabled true param to buildTypes section.
buildTypes {
debug {
testCoverageEnabled true
}
}
In this example it is in just for debug, but I believe if you add it for release it should also work.
Lastly add jacoco task like below;
task jacocoTestReport(type: JacocoReport, dependsOn: "testDebugUnitTest") {
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
reports {
xml.enabled = true
html.enabled = true
}
classDirectories = fileTree(
dir: './build/intermediates/classes/debug',
excludes: ['**/R*.class',
'**/*$InjectAdapter.class',
'**/*$ModuleAdapter.class',
'**/*$ViewInjector*.class'
])
sourceDirectories = files(coverageSourceDirs)
executionData = files("$buildDir/jacoco/testDebug.exec")
doFirst {
new File("$buildDir/intermediates/classes/").eachFileRecurse { file ->
if (file.name.contains('$$')) {
file.renameTo(file.path.replace('$$', '$'))
}
}
}
}
Using that task you should be able to create coverage reports. It will export html formatted coverage report in build folder.
For more information you can look at this tutorial.
I recently started integrating android-gradle-plugin 1.1.0 in one of my projects. The project uses robolectric 2.4 to run unit tests.
It's a multi module project with very complex dependencies (Some modules depend on other modules). Something like that:
--> application-module (dependsOn: module1, module2, module-core)
--> module1 (dependsOn: module-core)
--> module2 (dependsOn: module-core)
--> module-core (dependsOn: module3, module4)
--> module3 (library dependencies)
--> module4 (library dependencies)
For a more cleared picture please see jacoco-example project.
I tried to integrate JaCoCo to generate reports for the unit tests, but it seems to me that it runs only androidTests which are basically instrumentation tests.
After some google'ing I've come across a few projects on GitHub and other articles, but they mainly are focused on previous versions of the android-gradle-plugin or are using other third party plugins like android-unit-test for example here.
May be I've lost my ability to google. But can somebody point me in a direction where I can find some documentations regarding the new stuff in android gradle plugin and how to run the jacoco task only for unit tests?
UPDATE
Adopted the script from nenick's example:
apply plugin: "jacoco"
configurations {
jacocoReport
}
task jacocoReport(dependsOn: 'testDebug') << {
ant {
taskdef(name:'jacocoreport',
classname: 'org.jacoco.ant.ReportTask',
classpath: configurations.jacocoReport.asPath)
mkdir dir: "${buildDir}/test-coverage-report"
mkdir dir: "${buildDir}/reports/jacoco/test/"
jacocoreport {
executiondata = files("${buildDir}/jacoco/testDebug.exec")
structure(name: "${rootProject.name}") {
classfiles {
fileset (dir: "${buildDir}/intermediates/classes/debug") {
//exclude(name: '**/*_*.class')
exclude(name: '**/R.class')
exclude(name: '**/R$*.class')
exclude(name: '**/BuildConfig.class')
}
}
sourcefiles {
fileset dir: "src/main/java"
fileset dir: "${buildDir}/generated/source/buildConfig/debug"
fileset dir: "${buildDir}/generated/source/r/debug"
}
}
xml destfile: "${buildDir}/reports/jacoco/test/jacocoTestReport.xml"
html destdir: "${buildDir}/test-coverage-report/"
}
}
}
dependencies {
jacocoReport 'org.jacoco:org.jacoco.ant:0.7.2.201409121644'
}
After that the ./gradlew jacocoReport executes and generates the report, but it shows 0 (zero) test coverage, which is impossible because at least half of all classes are tested.
UPDATE_2
Tried out this example. Adding the next task to one of my gradle build files:
task jacocoTestReport(type:JacocoReport, dependsOn: "testDebug") {
group = "Reporting"
description = "Generate Jacoco coverage reports"
classDirectories = fileTree(
dir: "${buildDir}/intermediates/classes/debug",
excludes: ['**/R.class',
'**/R$*.class',
'**/*$ViewInjector*.*',
'**/BuildConfig.*',
'**/Manifest*.*']
)
sourceDirectories = files("${buildDir.parent}/src/main/java")
additionalSourceDirs = files([
"${buildDir}/generated/source/buildConfig/debug",
"${buildDir}/generated/source/r/debug"
])
executionData = files("${buildDir}/jacoco/testDebug.exec")
reports {
xml.enabled = true
html.enabled = true
}
}
Same issue, the reports are generated, but the code coverage is still zero.
UPDATE_3
It seams that the task from UPDATE_2 worked but only for the module with apply plugin: 'com.android.application' (The reports a generated correctly). But for modules that are android libraries (apply plugin: 'com.android.library') the reports show zero coverage, although the modules contain more tests then the application module.
UPDATE_4
Created a simple example project that demonstrates my issue. Currently if you run ./gradlew jacocoReport the report is generated, but no test coverage is displayed for the module projects. See this link
Short note: When the tests were AndroidUnitTests (whiteout JUnit 4 and Robolectric) JaCoCo reports showed coverage for all the modules.
Any ideas?
After the hassle, I decided to create an open source Gradle plugin for that.
Root build.gradle
buildscript {
repositories {
mavenCentral() // optional if you have this one already
}
dependencies {
classpath 'com.vanniktech:gradle-android-junit-jacoco-plugin:0.16.0'
}
}
apply plugin: 'com.vanniktech.android.junit.jacoco'
Then simply execute
./gradlew jacocoTestReportDebug
It'll run the JUnit tests in Debug Mode and then give you the Jacoco output in XML and HTML form in the corresponding build directory.
It also supports flavors. Having 2 flavors red and blue those tasks would be created
jacocoTestReportRedDebug
jacocoTestReportBlueDebug
jacocoTestReportRedRelease
jacocoTestReportBlueRelease
After some additional search I've stumbled upon this project
I had to make some modifications so that there solution can work for my type of project, but now the test coverage reports are generated properly.
I've pushed the adopted changes to my example github repo in case someone will have a similar problem in the future.
Warning: This is a hack! Using your configuration above, I put together a hack to switch the android plugin between application and library depending on the build tasks chosen. This works well for me because I don't end up committing code with the application mode set.
// dynamically change the android plugin to application if we are running unit tests or test reports.
project.ext.androidPlugin = 'com.android.library'
for (String taskName : project.gradle.startParameter.taskNames) {
if (taskName.contains('UnitTest') || taskName.contains('jacocoTestReport')) {
project.ext.androidPlugin = 'com.android.application'
break
}
}
logger.lifecycle("Setting android pluging to ${project.ext.androidPlugin}")
apply plugin: project.ext.androidPlugin
...
apply plugin: 'jacoco'
configurations {
jacocoReport
}
task jacocoTestReport(type:JacocoReport, dependsOn: "testDebug") {
group = "Reporting"
description = "Generate Jacoco coverage reports"
classDirectories = fileTree(
dir: "${buildDir}/intermediates/classes/debug",
excludes: ['**/R.class',
'**/R$*.class',
'**/*$ViewInjector*.*',
'**/BuildConfig.*',
'**/Manifest*.*']
)
sourceDirectories = files("${buildDir.parent}/src/main/java")
additionalSourceDirs = files([
"${buildDir}/generated/source/buildConfig/debug",
"${buildDir}/generated/source/r/debug"
])
executionData = files("${buildDir}/jacoco/testDebug.exec")
reports {
xml.enabled = true
html.enabled = true
}
}
Let's hope the android tools team fixes this soon.
I setup my unit tests for gradle 1.2 using this blog post. Then I pieced together information I found here and elsewhere to add code coverage to independent modules instead of the whole project. In my library module build.gradle file, I added the following:
apply plugin: 'jacoco'
def jacocoExcludes = [
'com/mylibrary/excludedpackage/**'
]
android {
...
}
android.libraryVariants.all { variant ->
task("test${variant.name.capitalize()}WithCoverage", type: JacocoReport, dependsOn: "test${variant.name.capitalize()}") {
group = 'verification'
description = "Run unit test for the ${variant.name} build with Jacoco code coverage reports."
classDirectories = fileTree(
dir: variant.javaCompile.destinationDir,
excludes: rootProject.ext.jacocoExcludes.plus(jacocoExcludes)
)
sourceDirectories = files(variant.javaCompile.source)
executionData = files("${buildDir}/jacoco/test${variant.name.capitalize()}.exec")
reports {
xml.enabled true
xml.destination "${buildDir}/reports/jacoco/${variant.name}/${variant.name}.xml"
html.destination "${buildDir}/reports/jacoco/${variant.name}/html"
}
}
}
And in my project build.gradle file, I added common excludes:
ext.jacocoExcludes = [
'android/**',
'**/*$$*',
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*Service.*'
]
Also, it looks like code coverage for unit tests may be coming built in in the future Issue 144664
I was finally able to see my code coverage of JUnit tests with Android Studio 1.1.
jacoco.gradle
apply plugin: 'jacoco'
jacoco {
toolVersion "0.7.1.201405082137"
}
def coverageSourceDirs = [
"$projectDir/src/main/java",
]
task jacocoTestReport(type: JacocoReport, dependsOn: "testDebug") {
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
reports {
xml.enabled = true
html.enabled = true
}
classDirectories = fileTree(
dir: './build/intermediates/classes/debug',
excludes: ['**/R*.class',
'**/*$InjectAdapter.class',
'**/*$ModuleAdapter.class',
'**/*$ViewInjector*.class'
]
)
sourceDirectories = files(coverageSourceDirs)
executionData = files("$buildDir/jacoco/testDebug.exec")
// Bit hacky but fixes https://code.google.com/p/android/issues/detail?id=69174.
// We iterate through the compiled .class tree and rename $$ to $.
doFirst {
new File("$buildDir/intermediates/classes/").eachFileRecurse { file ->
if (file.name.contains('$$')) {
file.renameTo(file.path.replace('$$', '$'))
}
}
}
}
and then within the build.gradle file of the module (I put it between android and dependencies):
apply from: '../jacoco.gradle'
Also in the defaultConfig block of android. I've added this (don't know if it is necessary, but I've got this from this blog):
android {
defaultConfig {
testHandleProfiling true
testFunctionalTest true
}
}
Enjoy.
You can try to use this Gradle plugin:
https://github.com/arturdm/jacoco-android-gradle-plugin
Basically, all you need to do is apply it like this:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.dicedmelon.gradle:jacoco-android:0.1.1'
}
}
apply plugin: 'com.android.library' // or 'com.android.application'
apply plugin: 'jacoco-android'
As a result you should get a JacocoReport task for each variant. Run the command below to generate code coverage reports for all of them.
$ ./gradlew jacocoTestReport
I resolve issues with JaCoCo and make it work with latest gradle android plugin 1.1.3
Project with latest gradle scripts: https://github.com/OleksandrKucherenko/meter
References:
How to attach own implementation instead of Mocks in Android Studio Unit Tests?
https://plus.google.com/117981280628062796190/posts/8jWV22mnqUB
Small hint for everyone who try to use JaCoCo coverage in android builds... unexpected finding!!!
https://plus.google.com/117981280628062796190/posts/RreU44qmeuP
JaCoCo XML/HTML Report for Unit Tests https://plus.google.com/u/0/+OleksandrKucherenko/posts/6vNWkkLed3b
I was facing exactly the same problem like you. Today I did completely removed android studio, android sdk, gradle. Then reinstall everything. After that, I just added inside the app build.gradle.
debug {
testCoverageEnabled true
}
Then I run ./gradlew connectedChec. Everything is working perfectly. Android studio default Jacoco working fine for me. I think it is also possible to create a jacocoTestReport Task and then create code coverage.I don't know why gradle and android studio was not working previously.
Please create an example and I can take a look. I guess it's some missing path configuration.
include all coverage files (*.exec)
add all your source paths (module/src/main/java)
add all class paths (module/build/intermediates/classes/debug)
here two examples how it could be look
https://github.com/nenick/AndroidAppDevelopment/blob/master/Scripts/jacoco-support-app-module.gradle
https://github.com/nenick/AndroidAppDevelopment/blob/master/Scripts/jacoco-coveralls-support.gradle
I'm evaluating the ability of the new gradle-based build system to reproduce our current ant-based build process and, as a gradle beginner, I failed to get checkstyle running with the android gradle plugin.
Environment:
gradle 1.6 running fine on a standard java project (checkstyle check target included)
up-to-date android SDK (22.0.1 with platform tools and build tools 17)
no eclipse, no android studio, only my lovely terminal
Symptom:
The target project is https://github.com/nibua-r/LigoTextDemo and I succeeded to build it using gradle but if I naively add apply plugin: checkstyle to my build.gradle:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.4.2'
}
}
apply plugin: 'android'
apply plugin: 'checkstyle'
android {
buildToolsVersion '17'
compileSdkVersion 15
testBuildType 'debug'
defaultConfig {
versionCode = 1
versionName = '1.0'
minSdkVersion 12
targetSdkVersion 15
}
buildTypes {
debug {
packageNameSuffix = '.debug'
}
}
}
then gradle check doesn't even complain on not finding the checkstyle.xml file (at the default config/checkstyle location) and returns:
:check UP-TO-DATE
BUILD SUCCESSFUL
What's needed:
First, I just need a running checkstyle target. Then, I need to automate checkstyle running as a dependency of the compilation (but lets get the chekstyle target up and running first).
Assumption:
This may be related to the fact that (from the [user guide][1]):
The Android plugin […] uses its own sourceSets
but I'm not enough gradle-efficient to understand what I'm missing there. Please, gradle Master, enlighten me with your valuable knowledge!
I got pmd, findbugs, and checkstyle working with Gradle 1.12 android plugin 0.12.+ using the following script:
apply plugin: 'checkstyle'
apply plugin: 'findbugs'
apply plugin: 'pmd'
check.dependsOn 'checkstyle', 'findbugs', 'pmd'
task checkstyle(type: Checkstyle) {
configFile file("${project.rootDir}/config/quality/checkstyle/checkstyle.xml")
source 'src'
include '**/*.java'
exclude '**/gen/**'
classpath = files()
}
task findbugs(type: FindBugs) {
ignoreFailures = true
effort = "max"
reportLevel = "high"
excludeFilter = new File("${project.rootDir}/config/quality/findbugs/findbugs-filter.xml")
classes = files("$project.buildDir/intermediates/classes/")
source 'src'
include '**/*.java'
exclude '**/gen/**'
reports {
xml {
destination "$project.buildDir/reports/findbugs/findbugs.xml"
xml.withMessages true
}
}
classpath = files()
}
task pmd(type: Pmd) {
ruleSetFiles = files("${project.rootDir}/config/quality/pmd/pmd-ruleset.xml")
ignoreFailures = true
ruleSets = ["basic", "braces", "strings"]
source 'src'
include '**/*.java'
exclude '**/gen/**'
reports {
xml.enabled = true
html.enabled = false
}
}
Running gradle build in command line will run all code quality plugins and generate xml reports in app/build/reports/ which are then ready to be viewed or parsed by CI tools.
Someone has a great answer to solve integrating PMD, findbugs and checkstyle with Gradle for Android.
Unfortunately, the only solution for now is based on ant :
http://sethrylan.org/2013/07/14/gradle-android-findbugs.html
I wish gradle will one day allow to do as much as maven for Android.
--- Update as of October 2013
With Gradle 1.8 and Android plugin for Gradle 0.6.+, you don't need this anymore. Android sourcesets and configurations are now compatible with the java plugin and all quality plugin work out of the box.
This includes pmd, findbugs, checkstyle and classycle.
--- Update
A configuration, largely inspired from the project mentioned above, is proposed in this open source project as well, plus other tools.
To get this to work with my Android project, I had to declare the task explicitly.
Here's what worked for me:
apply plugin: 'checkstyle'
task checkstyle(type: Checkstyle) {
source 'src'
include '**/*.java'
exclude '**/gen/**'
// empty classpath
classpath = files()
}
Be mindful that the Android plugin may choose to create a task of the same name in the future or work in conjunction with the checkstyle plugin in different ways.
You can try Android Check plugin (https://github.com/noveogroup/android-check):
Checkstyle
PMD
Configuration:
buildscript {
repositories { jcenter() }
dependencies {
...
classpath 'com.noveogroup.android:check:+'
...
}
}
apply plugin: 'com.noveogroup.android.check'
You can use hardcore configuration:
check {
abortOnError true
checkstyle { config hard() }
pmd { config hard() }
}
I found by digging on the web that the Android plugin depends on java-base and not java (i.e. the sourceSets management is specific) and the checkstyle plugin rely on java. As a consequence, some gradle upstream modification are needed to get the thing done. The gradle team is working on that, as seen on twitter:
#anzix Android source sets will be soon understood by the generic code quality plugins. Work on that has already started.— Gradle Build System (#Gradleware) May 26, 2013
Take a look at the Soter Gradle plugin to semlessly add support for Findbugs, Checkstyle and PMD to Android projects.