androidcode-coveragejacocoui-testingandroid-instrumentation

Multi module project Instrumentation test code coverage in non 'app' modules


I have a project structue like:

--app

--module2 //library module

--module3 //library module

I am writing instrumentation test cases for my multi module android project with jacoco code coverage. If I execute the instrumentation test cases from 'app' module, code coverage is only generated for 'app' module classes.

So, in order to get code coverage for 'module2' & 'module3' classes; I have written instrumentation test cases in respective modules.

Issue arises when I execute instrumentation test cases in non-app modules, am unable to launch the main activity, app is not launching during instrumentation and test cases are failing.

Root cause is:

@Rule
public ActivityTestRule<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);

@Rule is not declared in 'module2' & 'module3' which launch 'MainActivity.class'. I cannot import 'MainActiviy' to these modules because of some circular dependency issues.

Error:

java.lang.RuntimeException: No activities found. Did you forget to launch the activity by calling getActivity() or startActivitySync or similar?

How to tackle this ?

NB: This question is exclusively for instrumentation test, not for unit test(this is already handled in unit tests)

Similiar question


Solution

  • I have followed this anwer and changed the gradle task according to my requirments. Adding the gradle task for reference.

     task jacocoUiTestReportAllModules(type: JacocoReport, dependsOn: 'createDebugCoverageReport') {
        group "Reports"
        description "Generate Jacoco Instrumented Tests coverage reports for all modules"
        reports {
            xml.enabled = true
            html.enabled = true
            html.destination file("${rootProject.buildDir}/coverage-report")
        }
        def javaClasses = []
        def kotlinClasses = []
        def javaSrc = []
        def kotlinSrc = []
        def execution = []
        rootProject.subprojects.each { proj ->
            javaClasses << fileTree(dir: "$proj.buildDir/intermediates/javac/debug", excludes: fileFilter)
            kotlinClasses << fileTree(dir: "$proj.buildDir/tmp/kotlin-classes/debug", excludes: fileFilter)
            javaSrc << "$proj.projectDir/src/main/java"
            kotlinSrc << "$proj.projectDir/src/main/kotlin"
            execution << fileTree(dir: proj.buildDir, includes: [
                    'outputs/code_coverage/debugAndroidTest/connected/**/*.ec'])
        }
        getSourceDirectories().setFrom(files([javaSrc, kotlinSrc]))
        getClassDirectories().setFrom(files([javaClasses, kotlinClasses]))
        getExecutionData().setFrom(execution)
    
        doLast() {
            print "file://${reports.html.destination}/index.html"
    
        }
    }
    

    After running gradlew jacocoUiTestReportAllModules the report with full coverage will be present in [projRoot]/build/coverage-report.