Donal Rafferty
Donal Rafferty

Reputation: 19826

Jacoco failing on Parceler class - Android

I am using the Parceler library on Android (https://github.com/johncarl81/parceler)

And I am also using Jacoco for code coverage.

However after adding Parceler running my test code coverage with Jacoco now fails with the following error:

Caused by: java.io.FileNotFoundException: /Users/me/android/myapp/blah/app/build/intermediates/classes/demo/com/me/blah/appname/model/User$Parcelable$Creator$0.class (No such file or directory)

The User class is as follows:

@Parcel
public class User {

    @SerializedName("firstName")
    String firstName;

    @SerializedName("lastName")
    String lastName;

    @SerializedName("profileImage")
    ProfileImage profileImage;

    @SerializedName("username")
    String username;

    // empty constructor needed by the Parceler library
    public User() {
    }

}

And my Jacoco file is like this:

apply plugin: 'jacoco'

android {
    testOptions {
        unitTests.all {
            jacoco {
                includeNoLocationClasses = true
            }
        }
    }
}

project.afterEvaluate {

    android.applicationVariants.all { variant ->
        def name = variant.name
        def testTaskName = "test${name.capitalize()}UnitTest"

        tasks.create(name: "${testTaskName}Coverage", type: JacocoReport, dependsOn: "$testTaskName") {
            group = "Reporting"
            description = "Generate Jacoco coverage reports for the ${name.capitalize()} build."

            classDirectories = fileTree(
                    dir: "${project.buildDir}/intermediates/classes/${name}",
                    excludes: ['**/R.class',
                               '**/R$*.class',
                               '**/*$ViewInjector*.*',
                               '**/*$ViewBinder*.*',
                               '**/BuildConfig.*',
                               '**/Manifest*.*',
                               '**/*$ViewBinder*.*',
                               '**/*$ViewInjector*.*',
                               '**/Lambda$*.class',
                               '**/Lambda.class',
                               '**/*Lambda.class',
                               '**/*Lambda*.class',
                               '**/*InjectAdapter*.*',
                               '**/*StaticInjection*.*',
                               '**/*ModuleAdapter*.*']
            )

            sourceDirectories = files(['src/main/java'].plus(android.sourceSets[name].java.srcDirs))
            executionData = files("${project.buildDir}/jacoco/${testTaskName}.exec")

            reports {
                xml.enabled = true
                html.enabled = true
            }
        }
    }
}

I am wondering do I need to add the generated Parceler files to the excludes list in my Jacoco file? If so how do I do that? I have tried various variations but none seem to work.

The error complains that the following file is missing:

User$Parcelable$Creator$0.class

Which it is and instead the file is generated as follows:

User$$Parcelable.class

Can anyone explain this?

Upvotes: 1

Views: 571

Answers (2)

Dr.jacky
Dr.jacky

Reputation: 3547

Try this:

jacocoAndroidUnitTestReport {
    excludes += ['**/*Creator.class']
}

Upvotes: 1

Ihor Bykov
Ihor Bykov

Reputation: 1938

I just exclude it in jacocoAndroidCoverage.gradle, like this and it works now

def coverageSourceDirs = [
        '../app/src/main/java'
]

task jacocoStagingDebugCoverageReport(type:JacocoReport, dependsOn: ["connectedStagingDebugAndroidTest"]) {
    group = "Reporting"

    description = "Generate Jacoco coverage reports for staging debug"
    classDirectories = fileTree(
            dir: '../app/build/intermediates/classes/staging/debug/com/',
            excludes: ['**/R.class',
                       '**/R$*.class',
                       '**/*$ViewInjector*.*',
                       '**/*$ViewBinder*.*',
                       '**/*MembersInjector*.*',
                       '**/BuildConfig.*',
                       '**/Manifest*.*',
                       '**/*$Lambda$*.class',
                       '**/*Factory*.class',
                       '**/*$Builder*', 
                       '**/*$Parcelable*.*',
                       '**/*DaggerApplicationComponent*.class',
                       '**/api']
    )

    additionalSourceDirs = files(coverageSourceDirs)
    sourceDirectories = files(coverageSourceDirs)
    executionData = files('build/outputs/code-coverage/connected/flavors/staging/coverage.ec')

    reports {
        xml.enabled = true
        html.enabled = true
    }
}

Upvotes: 2

Related Questions