From ca3011d58974524dff9d167581dc8c2507c5ff3e Mon Sep 17 00:00:00 2001 From: "Zaw Myo Naing (Rahul)" Date: Mon, 15 Dec 2025 13:06:11 +0700 Subject: [PATCH 1/2] [#54] Migrate from Jacoco to Kover for test coverage reporting --- .github/workflows/review_pull_request.yml | 4 +- Dangerfile | 15 ++- app/build.gradle.kts | 15 +++ build.gradle.kts | 118 ++++++++-------------- common-ktx/build.gradle.kts | 8 ++ gradle/libs.versions.toml | 3 +- settings.gradle.kts | 4 +- 7 files changed, 78 insertions(+), 89 deletions(-) diff --git a/.github/workflows/review_pull_request.yml b/.github/workflows/review_pull_request.yml index 71195f8..e641284 100644 --- a/.github/workflows/review_pull_request.yml +++ b/.github/workflows/review_pull_request.yml @@ -39,8 +39,8 @@ jobs: - name: Run Android Lint run: ./gradlew lint - - name: Run unit tests and Jacoco - run: ./gradlew jacocoTestReport + - name: Run unit tests with Kover + run: ./gradlew koverXmlReportCustom - name: Set up Ruby uses: ruby/setup-ruby@v1 diff --git a/Dangerfile b/Dangerfile index 5627252..e94ff6b 100644 --- a/Dangerfile +++ b/Dangerfile @@ -29,12 +29,9 @@ Dir[lint_dir].each do |file_name| android_lint.lint(inline_mode: true) end -# TODO: Update to support test coverage report from Jacoco for Coroutine Template -# Show Danger test coverage report from Jacoco for RxJavaTemplate -jacoco_dir = "RxJavaTemplate/**/build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml" -markdown "## RxJavaTemplate Jacoco report:" -Dir[jacoco_dir].each do |file_name| - # Report coverage of modified files, warn if total project coverage is under 80% - # or if any modified file's coverage is under 95% - shroud.report file_name, 80, 95, false -end +# Show Danger test coverage report from Kover +# Report coverage of modified files, warn if total project coverage is under 80% +# or if any modified file's coverage is under 95% +kover_file = "app/build/reports/kover/reportCustom.xml" +markdown "## Kover report for Android Common Extensions" +shroud.reportKover moduleName: "Android Common Extensions Unit Tests", file: kover_file, totalProjectThreshold: 80, modifiedFileThreshold: 95, failIfUnderProjectThreshold: false, failIfUnderFileThreshold: false diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 92c43fa..2a3afa1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -51,3 +51,18 @@ dependencies { androidTestImplementation(libs.test.ext.junit) androidTestImplementation(libs.test.espresso.core) } + +/* + * Kover configs + */ +dependencies { + kover(projects.commonKtx) +} + +kover { + currentProject { + createVariant("custom") { + add("debug") + } + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 474a653..09a0c76 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,11 +1,11 @@ -import org.gradle.api.tasks.testing.Test +import kotlinx.kover.gradle.plugin.dsl.KoverProjectExtension plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.android.library) apply false alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.kover) apply false alias(libs.plugins.detekt) - jacoco } dependencies { @@ -31,81 +31,47 @@ detekt { ignoredFlavors = listOf("production") } -jacoco { - toolVersion = libs.versions.jacoco.get() -} - -val fileGenerated = listOf( - "android/**/*.*", - "**/R.class", - "**/R\$*.class", - "**/*\$ViewBinder*.*", - "**/*\$InjectAdapter*.*", - "**/*Injector*.*", - "**/BuildConfig.*", - "**/Manifest*.*", - "**/*_ViewBinding*.*", - "**/*_Factory*.*", - "**/app/ui/screens/**/*DiffCallback*.*", - "**/*Test*.*", - // navigation component - "**/*FragmentArgs*", - "**/*FragmentDirections*", - "**/FragmentNavArgsLazy.kt", - "**/*Fragment*navArgs*", - "**/screens/common/StartFragment.*", - // kotlin enum Creator - "**/*\$Creator*" -) - -val packagesExcluded = listOf( - "co/nimblehq/extensions/app/**", - "com/bumptech/glide" -) - -val fileFilter = fileGenerated + packagesExcluded - -tasks.register("jacocoTestReport") { - group = "Reporting" - description = "Generate Jacoco coverage reports for Debug build" - - dependsOn(":app:testDebugUnitTest") - dependsOn(":common-ktx:testDebugUnitTest") - - classDirectories.setFrom( - fileTree("${project.rootDir}/app/build/intermediates/javac/debug/classes") { - exclude(fileFilter) - }, - fileTree("${project.rootDir}/common-ktx/build/intermediates/javac/debug/classes") { - exclude(fileFilter) - }, - fileTree("${project.rootDir}/app/build/tmp/kotlin-classes/debug") { - exclude(fileFilter) - }, - fileTree("${project.rootDir}/common-ktx/build/tmp/kotlin-classes/debug") { - exclude(fileFilter) +subprojects { + apply(plugin = "org.jetbrains.kotlinx.kover") + configure { + reports { + filters { + excludes { + androidGeneratedClasses() + annotatedBy( + "androidx.annotation.VisibleForTesting" + ) + classes( + // View Binding & Data Binding + "**/*_ViewBinding*", + "**/*_Factory*", + "**/*\$ViewBinder*", + "**/*\$InjectAdapter*", + "**/*Injector*", + "*.*_ComponentTreeDeps*", + "*.*_HiltComponents*", + "*.*_MembersInjector*", + "*\$InstanceHolder", + // Navigation Component + "**/*FragmentArgs*", + "**/*FragmentDirections*", + "**/FragmentNavArgsLazy*", + "**/*Fragment*navArgs*", + "**/screens/common/StartFragment*", + // DiffCallback + "**/app/ui/screens/**/*DiffCallback*", + // Kotlin Enum Creator + "*.*\$Creator*", + // Test files + "**/*Test*" + ) + packages( + "co.nimblehq.extensions.app", + "com.bumptech.glide" + ) + } + } } - ) - - sourceDirectories.setFrom( - files( - "${project.rootDir}/app/src/main/java", - "${project.rootDir}/common-ktx/src/main/java" - ) - ) - - executionData.setFrom( - fileTree(project.rootDir) { - include( - "app/build/jacoco/testDebugUnitTest.exec", - "common-ktx/build/jacoco/testDebugUnitTest.exec" - ) - } - ) - - reports { - xml.required.set(true) - html.required.set(true) } } diff --git a/common-ktx/build.gradle.kts b/common-ktx/build.gradle.kts index 4fd222a..f601dcb 100644 --- a/common-ktx/build.gradle.kts +++ b/common-ktx/build.gradle.kts @@ -75,3 +75,11 @@ afterEvaluate { } } } + +kover { + currentProject { + createVariant("custom") { + add("debug") + } + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f05cf5b..4cdc9cb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ detekt = "1.23.8" gradle = "8.13.0" gson = "2.8.9" hamcrest = "1.3" -jacoco = "0.8.12" +kover = "0.9.3" junit = "4.13.2" kotlin = "2.2.21" material = "1.4.0" @@ -43,3 +43,4 @@ android-application = { id = "com.android.application", version.ref = "gradle" } android-library = { id = "com.android.library", version.ref = "gradle" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 8e60b82..2950b84 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,6 +14,8 @@ dependencyResolutionManagement { } } -rootProject.name = "Android Extensions" +rootProject.name = "AndroidExtensions" +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + include(":app") include(":common-ktx") From e363a98d3ada5693bc870d04e1c1ad240ada480d Mon Sep 17 00:00:00 2001 From: "Zaw Myo Naing (Rahul)" Date: Tue, 16 Dec 2025 16:09:47 +0700 Subject: [PATCH 2/2] [#54] Sort version variable alphabetically --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4cdc9cb..687d31a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,9 +15,9 @@ detekt = "1.23.8" gradle = "8.13.0" gson = "2.8.9" hamcrest = "1.3" -kover = "0.9.3" junit = "4.13.2" kotlin = "2.2.21" +kover = "0.9.3" material = "1.4.0" [libraries]