Did anyone figure out how to configure JaCoCo in a...
# multiplatform
s
Did anyone figure out how to configure JaCoCo in a KMM project? It started with the Compose for Desktop Template (from the Wizard), but it does not seem possible to activate JaCoCo if also the "android-library" plugin is applied. So is there no way to report code coverage to sonarqube via gradle in Multiplatform projects?
r
FYI, jacoco is not working with kotlin 1.5
👍 1
s
Is that a Kotlin or a JaCoCo problem? Is Kotlin producing invalid Java bytecode here?
k
Jacaco fixed those issues in 0.8.7: https://www.jacoco.org/jacoco/trunk/doc/changes.html
c
Jacoco works fine with Kotlin 1.5 & 1.5.10 if you use the latest version: https://gitlab.com/clovis-ai/formulaide/-/blob/main/server/build.gradle.kts#L41
s
Yeah, but that's a JVM project. My project is Kotlin Multiplatform like this: https://github.com/JetBrains/compose-jb/blob/master/templates/multiplatform-template/common/build.gradle.kts
The JaCoCo Plugin can be added, but it does not even generate tasks. Nothing works.
And it seems not be an Kotlin 1.5 problem because 1.4.32 does not work either
It's hard to believe nobody working on a KMM library tracks code coverage in SonarQube/Codecov right now 🤔
c
Jacoco is a JVM analysis tool, it's not going to work on other platforms. If you want coverage in other platforms, you'll have to find an equivalent tool there.
s
I want coverage for "jvmMain"
I'm aware of that. I just want to coverage the java code
But that does not work
How do I have to configure that project that I get code coverage for the java part?
Nice to see that the team is actually working on a code coverage tool. It's really needed.
c
Jacoco coverage works fine for multiplatform, and will work for code under commonMain and jvmMain.
Copy code
val isCoverageEnabled = run {
    val isCoverageEnabled: String by project
    isCoverageEnabled.toBoolean()
}
if (isCoverageEnabled) {
    apply(plugin = "java-library")
    apply(plugin = "jacoco")

    configure<JacocoPluginExtension> {
        val jacocoVersion: String by project
        toolVersion = jacocoVersion
    }

    afterEvaluate {
        tasks.withType<JacocoReport>().configureEach {
            classDirectories.setFrom(
                fileTree("${buildDir}/classes/kotlin/jvm/") {
                    exclude("**/*Test*.*", "**/*Fixture*.*")
                }
            )

            sourceDirectories.setFrom(
                // This could be better if it dynamically got the source directories, e.g. more along the lines of
                // kotlin.sourceSets["commonMain"].kotlin.sourceDirectories,
                // kotlin.sourceSets["jvmMain"].kotlin.sourceDirectories
                listOf("src/commonMain/kotlin", "src/jvmMain/kotlin")
            )
            executionData.setFrom("${buildDir}/jacoco/jvmTest.exec")
        }
    }
}
Then
./gradlew check -PisCoverageEnabled=true; ./gradlew jacocoTestReport -PisCoverageEnabled=true
I found it necessary to run the check and jacocoTestReport tasks serially.
s
Thanks. Do you have Android in your KMM project? Running this I get
The 'java' plugin has been applied, but it is not compatible with the Android plugins.
Because the shared common project imports also
Copy code
id("com.android.library")
And without applying
Copy code
java-library
there seems to be no jaCoCoTestReport Task
c
My project is multiplatform compose app with common, java (compose desktop), and javascript (compose web). Android has its own configuration for coverage. I’ve only configured Android independently of the other platforms.
s
Ah, ok, thank you.
Maybe it's just KMM modules with Android that can't have jacoco coverage
846 Views