Jacoco and Unit Tests Code Coverage with android- gradle -plugin> = 1.1

I recently started integrating android-gradle-plugin 1.1.0 into one of my projects. The project uses robolectric 2.4 to run unit tests.

This is a project with several modules 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 cleaner image, see the jacoco-example project.

I tried to integrate JaCoCo to create reports for unit tests, but it seems to me that it only works androidTests , which are mostly instrumental tests.

After some google'ing, I came across several projects on GitHub and other articles, but they mainly focus on previous versions of android-gradle-plugin or use other third-party plugins such as android-unit-test for example here .

I may have lost the ability of Google. But can someone point me in the direction where I can find the documentation regarding the new material in the android gradle plugin and how to run the jacoco task only for unit tests?

UPDATE

Took a script from nenick 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 ./gradlew jacocoReport executes and generates a report, but it shows 0 (zero) test coverage, which is impossible because at least half of all classes are tested.

UPDATE_2

Tried this example . Adding the following 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 } } 

The same problem, reports are generated, but the coverage of the code is still zero.

UPDATE_3

This means that the task from UPDATE_2 worked, but only for the module with apply plugin: 'com.android.application' (reports are 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 than the software module.

UPDATE_4

Created a simple example demonstrating my problem. Currently, if you run ./gradlew jacocoReport , a report is generated, but test coverage is not displayed for module projects. See Link

Brief note:. When the tests were AndroidUnitTests (whiteout JUnit 4 and Robolectric), JaCoCo reports showed coverage for all modules.

Any ideas?

+35
android android-gradle unit-testing jacoco
Feb 18 '15 at 15:10
source share
9 answers

After the hassle, I decided to create an open source Gradle plugin for this.

Root build.gradle

 buildscript { repositories { mavenCentral() // optional if you have this one already } dependencies { classpath 'com.vanniktech:gradle-android-junit-jacoco-plugin:0.8.0' } } apply plugin: 'com.vanniktech.android.junit.jacoco' 

Then just do

 ./gradlew jacocoTestReportDebug 

It will run the JUnit tests in debug mode, and then give you Jacoco output in xml and html format in the appropriate build directory.

It also supports aromas. Having 2 flavors of red and blue, these tasks will be created

  • jacocoTestReportRedDebug
  • jacocoTestReportBlueDebug
  • jacocoTestReportRedRelease
  • jacocoTestReportBlueRelease
+11
Oct 11 '15 at 11:36
source share

After some additional searching, I came across this project. I had to make some changes so that the solution could work for my type of project, but now test coverage reports are generated properly.

I introduced the accepted changes in my github repo example if someone has the same problem in the future.

+8
Apr 13 '15 at 14:09
source share

I am installing my unit tests for gradle 1.2 using this blog post . Then I gathered information that I found here and elsewhere to add code coverage to independent modules instead of the entire project. In my build.gradle library module build.gradle 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 general exceptions:

 ext.jacocoExcludes = [ 'android/**', '**/*$$*', '**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Service.*' ] 

Also, it looks like code coverage for unit tests may appear in the future. Problem 144664

+3
Jun 03 '15 at 19:53
source share

Warning: This is a hack! Using your configuration above, I collected a hacked key to switch the android plugin between the application and the library depending on the selected build tasks. This works well for me because I am not completing the 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 } } 

We hope that the Android development team will fix this soon.

+2
Feb 21 '15 at 17:13
source share

Finally, I was able to see my JUnit test code coverage in 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 in the module build.gradle file (I installed it between android and dependencies ):

 apply from: '../jacoco.gradle' 

Also in the defaultConfig android block. I added this (I don’t know if this is necessary, but I got it from this blog ):

 android { defaultConfig { testHandleProfiling true testFunctionalTest true } } 

Enjoy.

+2
Mar 18 '15 at 13:55
source share

I solve problems with JaCoCo and make it work with the latest gradle Android 1.1.3 plugin

Project with latest gradle scripts: https://github.com/OleksandrKucherenko/meter

Literature:

How to connect my own implementation instead of Mocks in Android Studio Unit Tests? https://plus.google.com/117981280628062796190/posts/8jWV22mnqUB

A small hint for anyone trying to use JaCoCo in Android builds, an unexpected discovery !!! https://plus.google.com/117981280628062796190/posts/RreU44qmeuP

JaCoCo XML / HTML report for unit tests https://plus.google.com/u/0/+OleksandrKucherenko/posts/6vNWkkLed3b

+1
Mar 10 '15 at 10:25
source share

I had the same problem as you. Today I completely uninstalled android studio, android sdk, gradle. Then reinstall everything. After that, I just added build.gradle to the application.

debug {testCoverageEnabled true} Then I run. / gradlew connectedChec. Everything works perfectly. The default android studio Jacoco works great for me. I think it is also possible to create a jacocoTestReport Task, and then create code coverage. I do not know why gradle and android studio did not work before.

+1
Mar 19 '15 at 19:49
source share

You can use this Gradle plugin: https://github.com/arturdm/jacoco-android-gradle-plugin

Basically, all you have to do is apply it as follows:

 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 option. Run the command below to generate code coverage reports for all of them.

 $ ./gradlew jacocoTestReport 
+1
Sep 14 '15 at 19:16
source share

Please create an example and I can take a look. I assume this is the missing path configuration.

  • include all coverage files (* .exec)
  • add all source paths (module / src / main / java)
  • add all class paths (module / assembly / intermediate / classes / debugging)

here are two examples of how it looked

0
Feb 26 '15 at 9:18
source share



All Articles