29

I am trying to generate Jacoco code coverage report. I have used AndroidTestCase for my test classes.

I have found using testCoverageEnabled true and using default android -studio default jacoco, ./gradlew connectedCheck or createDebugCoverageReport create the percentage of successfull/fail test cases, but no coverage report.

Then I have tried jacoco {toolVersion "0.7.1.201405082137"}, and task jacocoTestReport(type:JacocoReport, dependsOn: "testDebug"). I have tried to change the dependsOn value with various task. The report shows 0 (zero) test coverage, which is impossible because at least half of all classes are tested.

I have followed various accepted answer of stack overflow in last couple of days. The result is negative.

My gradle file:

buildscript {
    repositories {
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.0.0'        
    }
}

apply plugin: 'com.android.application'
apply plugin: 'jacoco'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "test.gradle.com.myapplicationtestgradle"
        minSdkVersion 21
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled false            
            proguardFiles getDefaultProguardFile(
            'proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            testCoverageEnabled true
        }
    }

    jacoco {
        version "0.7.1.201405082137"
    }

    packagingOptions {
        exclude 'LICENSE.txt'
    }
}


jacoco {
    toolVersion "0.7.1.201405082137"
}

task jacocoTestReport(type:JacocoReport, dependsOn: "testDebug") {
    group = "Reporting"

    description = "Generate Jacoco coverage reports"

   // exclude auto-generated classes and tests
    def fileFilter = ['**/R.class', '**/R$*.class', 
    '**/BuildConfig.*', '**/Manifest*.*',           
     'android/**/*.*']
    def debugTree = fileTree(dir:   
    "${project.buildDir}/intermediates/classes/debug", 
    excludes: fileFilter)
    def mainSrc = "${project.projectDir}/src/main/java"

    sourceDirectories = files([mainSrc])
    classDirectories = files([debugTree])
    additionalSourceDirs = files([
            "${buildDir}/generated/source/buildConfig/debug",
            "${buildDir}/generated/source/r/debug"
    ])
    executionData = fileTree(dir: project.projectDir, includes: 
                    ['**/*.exec', '**/*.ec'])

    reports {
        xml.enabled = true
        xml.destination = "${buildDir}/jacocoTestReport.xml"
        csv.enabled = false
        html.enabled = true
        html.destination = "${buildDir}/reports/jacoco"
    }
}


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('junit:junit:4.11') {
        exclude module: 'hamcrest-core'
    }
}
user1365169
  • 383
  • 1
  • 3
  • 10

5 Answers5

50

Gradle already has built-in support for generating test coverage reports and we don't need to create any additional configurations or add any plugins to generate test coverage report. Basically, the only thing we need to do is to set testCoverageEnabled parameter to true in build.gradle file as follows:

android {
   buildTypes {
      debug {
         testCoverageEnabled = true
      }
   }
}

Next, we can execute the following Gradle task from CLI:

./gradlew createDebugCoverageReport

On Windows, we can execute it like this:

gradlew.bat createDebugCoverageReport

Task will analyze code of our project in /src/main/java/ directory and unit tests placed in /src/androidTest/java/ directory. After executing this task, we can find test coverage report in the following directory of the module:

/build/outputs/reports/coverage/debug/

When we open index.html file, we can see a visual report from test coverage, which can be viewed in a web browser.

It looks as on the image below.

enter image description here

I've written an article about test coverage report in Android application and published it on my blog some time ago. If you are interested in that topic, you can read it at:

Update (Unit test coverage for Robolectric tests)

If you would like to create test coverage report from unit tests written with Robolectric and generate test coverage report with Jacoco, Travis CI and Codecov.io, please take a look at the new article on my blog:

Piotr Wittchen
  • 3,853
  • 4
  • 26
  • 39
  • 6
    Only issue I see is that the /src/androidTest/java is not the default when using JUnit on Android Studio. /src/test/java is the directory. Any clue how to override that directory? – BK- Oct 26 '15 at 23:55
  • In my case, I had all tests in `/src/androidTest/java` and test coverage report was still generated correctly. I haven't checked how it works when you put all tests to `/src/test/java` or part of the tests (plain java) to one directory and another part (android) to the different directory. – Piotr Wittchen Oct 27 '15 at 09:24
  • But we have to understand android studio itself uses jacoco to generate the test reports. – dsharew Dec 02 '15 at 06:18
  • 1
    Seems to be broken with Android studio 2.0, gradle plugin 2.0.0, have you tried it? – jlhonora Jan 26 '16 at 22:08
  • I haven't tried it. As far as I see, Android Studio 2.0 is not official yet and is preview release, so may have bugs. Moreover, you should be able to run it without Android Studio from command line. All you need is project source code, Gradle Wrapper and Gradle configuration. – Piotr Wittchen Jan 27 '16 at 19:26
  • I find your answer misleading. I did all the steps and what I am viewing is a very basic report generated under the `reports/androidTest` directory. Nothing like the detailed Jacoco report you posted. I think I should add the jacoco plugin for this to work. – Mister Smith Feb 24 '16 at 17:51
  • Please check, that you're compiling app in debug variant and check `/build/outputs/reports/coverage/debug/` directory, because coverage report should be placed there. I haven't tested it with the newest Android API and Android Studio and this may be the potential problem. – Piotr Wittchen Feb 24 '16 at 17:55
  • how to generate this report in android studio 1.51 and gradle 2.4 I get error Task 'createDebugCoverageReport' not found in root project 'android'. I need code coverage exactly like shown above not test coverage which jococo seems to create with test{flavour}debug – ir2pid Apr 21 '16 at 05:01
  • @ir2pid Have you set `testCoverageEnabled` to `true` as shown in the main post? Then, you should have this task. Android Studio is not a problem. You should be able to generate it without Android Studio, directly from console. – Piotr Wittchen Apr 21 '16 at 07:14
  • yes, testCoverageEnabled is set to true. I'm running in terminal, ./gradlew tasks doesn't show this command – ir2pid Apr 21 '16 at 08:01
  • Maybe something changed or your setup is different. Note that this answer is one year old and Android changes dynamically. I can check it later. – Piotr Wittchen Apr 25 '16 at 14:44
  • @ir2pid Have you tried `create{flavor}CoverageReport`? – ubuntudroid May 06 '16 at 19:21
  • I need to use `jacocoTestCoverageVerification`, but the usual code in whole of the Internet not working and gradle doesn't know that. can you help me? @piotr.wittchen – MHSaffari Oct 02 '19 at 05:43
  • I updated links in my post. I'm not sure if the solution is fully up to date because this answer is 4 years old now. – Piotr Wittchen Oct 02 '19 at 13:07
  • Cannot find the /build/outputs/reports/coverage/ folder after running the task, anyone else with this problem? – Jesus Almaral - Hackaprende May 29 '20 at 17:01
  • Shouldn't unit tests be stored in `src/test/java`? `src/androidTest/java` is reserved for UI/instrumentation tests. – Tianyao 'Till' Chen Feb 24 '22 at 02:23
  • This answer may not be up to date (I answered it 7 years ago) and some adjustments in the project configuration may be required. Previously, I needed to put all tests in the `androidTest` directory to make it work. The `androidTest` directory contains instrumentation tests executed on emulator/device and the `test` directory contains pure unit tests written in Java. Right now, the newest jacoco gradle plugin should be able to handle generation of test coverage using those two directories. – Piotr Wittchen Feb 26 '22 at 19:03
15

I see that you already got it working, however, there's a simpler method for getting Unit Test execution data. I recently was looking into this as well, I actually made a full write up earlier today.

In my situation, I didn't want to create an additional Gradle task as I wanted the report to be generated as a part of the existing workflow. I also didn't want to explicitly add the Jacoco plugin, as Google already dups the Jacoco Ant tasks for the coverage reports for Instrumentation Tests.

In addition to setting the properties android.jacoco.version and buildTypes.debug.testCoverageEnabled, I added the following to the testDebug JVM arguments to generate execution data:

project.afterEvaluate {
  def append = "append=true"
  def destFile = "destfile=$buildDir/outputs/code-coverage/connected/coverage.ec"
  testDebug.jvmArgs "-javaagent:$buildDir/intermediates/jacoco/jacocoagent.jar=$append,$destFile"

  createDebugCoverageReport.dependsOn testDebug
}

This appends the Unit Test execution data to the coverage file generated by connectedAndroidTest, so your report reflects both Instrumentation Tests and Unit Tests, rather than each variant individually.

Note that connectedAndroidTest overwrites the coverage file, take this into account when creating your report. If the task testDebug doesn't have any changes, and you run createDebugCoverageReport, it will only reflect your Instrumentation Test coverage. So, make a change to your Unit Tests. The Linux command touch may be useful here, although I haven't tried yet.

Patrick McLaren
  • 978
  • 10
  • 22
  • Just referencing what seems to be the canonical method for getting any type of coverage report generated, see [this](http://stackoverflow.com/q/23795595/269300) SO question - for anyone who is having trouble getting `createDebugCoverageReport` to appear. – Patrick McLaren Mar 19 '15 at 20:11
  • 1
    I have already seen that accepted answer. I think. you are right for both Instrumentation Tests and Unit Tests. I do need to look at the (testDebug.jvmArgs). Thank you very much for explain some useful information. – user1365169 Mar 20 '15 at 15:29
  • This doesn't seem to merge both reports for me. It only includes coverage from android tests, not unit tests. I'm using mutliple flavors, but I changed `project.afterEvaluate` accordingly. Any idea? – Gaëtan Apr 09 '15 at 07:58
  • I'm getting an UNEXPECTED TOP-LEVEL EXCEPTION: com.android.dex.DexException: Multiple dex files define L(*noOfMyclasses*). When I run createDebugCoverageReport or connectedCheck. Which I don't have when I run jacocoTestReport. The last give me a successful build, but no code coverage. I removed the class that broke the build, but another class now broke the build... Any idea? – Hugo Oshiro Jun 11 '15 at 12:43
  • Have you tried to clean the project? There should be some appropriately named tasks that will clean your required libs. Then, try building again. – Patrick McLaren Jun 15 '15 at 15:42
  • Noob question : where exactly one will put this code? I have put it under my 'task' and yet it is skipping `jacocoTestReport` task – Darpan Jul 24 '15 at 09:46
  • I placed this code in the top-level of my `build.gradle`, not within a task. Also, my approach was to ensure that the unit test task `testDebug` was a dependency of `createDebugCoverageReport` (typically instrumentation tests only), so I could obtain a full coverage report in one fell swoop. I didn't use the `jacocoTestReport` task. – Patrick McLaren Jul 24 '15 at 14:49
  • 3
    what is `testDebug` and where do I add it? – behelit Mar 17 '16 at 03:52
  • 1
    Does not work on Android Studio 2.1.2 `Error:Could not find property 'testDebug' on project ':myproject'`. So I renamed to `testDebugUnitTest` but it does not process coverage for added unit tests. – Guillaume Perrot Jun 27 '16 at 19:27
  • link `earlier today` is broken. – vida Mar 28 '17 at 09:29
  • 1
    @vida I fixed the broken link, thanks for letting me know! – Patrick McLaren Mar 29 '17 at 19:27
  • 1
    I am getting the error: Error:(224, 0) Could not get unknown property 'testDebug' for project. How to solve this ?? – remya thekkuvettil Jul 04 '17 at 09:52
3

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.

Henning
  • 2,202
  • 1
  • 17
  • 38
user1365169
  • 383
  • 1
  • 3
  • 10
1

i investigated correct way to get merged code coverage report with Jacoco, you can check it here: https://gist.github.com/ultraon/54cca81ca159ed0a4a9ebf62e89c26ba

I used AndroidStudio 2.2.2 with Gradle 3.2 and Android Gradle Plugin 2.2.2

ultraon
  • 2,220
  • 2
  • 28
  • 27
0

I had the same problem too, but I made a mistake in the process which took a few days to track down. Here's my technique and the gotcha that caused the 0% coverage.

  1. Install jacoco. I used the technique described in great detail here with a few modifications because of my project's structure. Thank you Ashish Uniyal!

  2. Run jacoco. Open the Gradle window in Android Studio (View -> Tool Windows -> Gradle), click on the elephant icon to "Execute Gradle Task."
    enter image description here

If a pop-up to your settings occurs, go ahead and disable the "Do not build Gradle task list during Gradle sync."

In the text window that pops up after clicking the elephant icon, type in: gradle app:createDebugUnitTestCoverageReport and hit [Enter]. enter image description here If you want to do AndroidTests, type gradle app:createDebugAndroidTestCoverageReport.

It'll take several seconds to a few minutes to execute jacoco.

  1. Find the results. This can vary depending on your settings in the jacoco.gradle file. But generally you can find the results an index.html file here: ./app/build/reports/coverage/test/debug/index.html.

My big gotcha was that I typed in the AndroidTest instead of the UnitTest (thank you auto-complete, sigh). Since I only did unit testing all jacoco could see was a big fat 0%.

SMBiggs
  • 11,034
  • 6
  • 68
  • 83