Search code examples
androidtestinggradlecode-coveragejacoco

How to find the code coverage of an android application for manual testing?


I want to find the code coverage of manual testing and automatic testing (appium) for an Android app (Android studio + gradle).

There are a few questions related to this problem on StackOverflow already but none of them works for me. I have followed the steps of this question: Android Coverage launch with JaCoCo The jacoco.exec file that is being generated in sdcard/ is 37 bytes and is basically empty.

Current configuration of build.gradle:

apply plugin: 'com.android.application'

apply plugin: 'jacoco'
def coverageSourceDirs = [
        '../app/src/main/java'
]

jacoco{
    toolVersion = "0.7.4.201502262128"
}

task jacocoTestReport(type: JacocoReport) {
    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/outputs/code-coverage/connected/coverage.exec")
    doFirst {
        new File("$buildDir/intermediates/classes/").eachFileRecurse { file ->
            if (file.name.contains('$$')) {
                file.renameTo(file.path.replace('$$', '$'))
            }
        }
    }
}
// this is for the report
...

jacoco.java:

package anubhav.calculatorapp;

import android.util.Log;

import java.lang.reflect.Method;

public class jacoco {
    static void generateCoverageReport() {
        String TAG = "jacoco";
        // use reflection to call emma dump coverage method, to avoid
        // always statically compiling against emma jar
        String coverageFilePath = "/sdcard/coverage.exec";
        java.io.File coverageFile = new java.io.File(coverageFilePath);
        try {
            Class<?> emmaRTClass = Class.forName("com.vladium.emma.rt.RT");
            Method dumpCoverageMethod = emmaRTClass.getMethod("dumpCoverageData",
                    coverageFile.getClass(), boolean.class, boolean.class);

            dumpCoverageMethod.invoke(null, coverageFile, false, false);
            Log.e(TAG, "generateCoverageReport: ok");
        } catch (Exception  e) {
            Log.e("jacoco", "inside catch. no emma jar found");
            new Throwable("Is emma jar on classpath?", e);
        }
    }
}

Solution

  • Make these changes into the build.gradle file:

    apply plugin: 'jacoco' 
    

    Also add testCoverageEnabled true to the debug {} in buildTypes. I cannot emphasize the importance of testCoverageEnabled, it instruments the files and you won't be able to get coverage without it. Make sure this line is added correctly.

    For correct setup of 'build.gradle' check the 'build/intermediates'.

    Add read and write external storage permission to the AndroidManifest.xml

    In the onDestroy() function of the MainActivity.java add these lines:

    Log.d("StorageSt", Environment.getExternalStorageState());
            String coverageFilePath = Environment.getExternalStorageDirectory() + File.separator+ "coverage.exec";
            File coverageFile = new File(coverageFilePath);
            super.onStop();
            if(BuildConfig.DEBUG)
            {
                try {
                    Class<?> emmaRTClass = Class.forName("com.vladium.emma.rt.RT");
                    Method dumpCoverageMethod = emmaRTClass.getMethod("dumpCoverageData",coverageFile.getClass(),boolean.class,boolean.class);
                    dumpCoverageMethod.invoke(null, coverageFile,true,false);
                }
                catch (Exception e) {}
    

    Run your app and you'll find the coverage.exec in /sdcard/. If the coverage is 37bytes on emulator, try it on a real device or build the APK and drop it into the emulator to install it.

    You can then pull the coverage.exec into your computer and generate the HTML report from it using jacoco.