Code Coverage with Kover
Relevant source files
The following files were used as context for generating this wiki page:
- build-logic/convention/src/main/kotlin/KoverConventionPlugin.kt
- build-logic/convention/src/main/kotlin/com/vocabri/KoverConfiguration.kt
- domain/src/main/java/com/vocabri/domain/model/kover/ExcludeFromCoverage.kt
- build-logic/convention/src/main/kotlin/ProjectConventionPlugin.kt
- README.md
- gradle/libs.versions.toml
- app/src/main/java/com/vocabri/di/AppModule.kt
- domain/src/main/java/com/vocabri/domain/di/DomainModule.kt
The Vocabri project utilizes Kover to measure code coverage by tests. It is an essential part of the project's quality assurance toolkit, alongside Spotless for code formatting and Detekt for static analysis. Kover helps identify parts of the codebase that are not covered by unit or instrumented tests, ensuring higher code quality and maintainability.
Integration is managed through a series of custom Gradle convention plugins located in the build-logic directory. This ensures that code coverage is configured consistently across all modules of the project.
Sources: README.md:27-28, build-logic/convention/src/main/kotlin/ProjectConventionPlugin.kt:28-29
Gradle Integration
Kover is integrated into the project's build system via a custom ProjectConventionPlugin. This plugin automatically applies the Kover plugin and its specific configuration to all subprojects, standardizing the code coverage setup.
Sources: build-logic/convention/src/main/kotlin/ProjectConventionPlugin.kt:26-32
Plugin Application Flow
The following diagram illustrates how the Kover plugin and its configuration are applied during the Gradle build process.
This diagram shows that the ProjectConventionPlugin is the central point for applying both the Kover plugin itself (applyKover) and the project-specific exclusion rules (applyKoverExclusions).
Sources: build-logic/convention/src/main/kotlin/ProjectConventionPlugin.kt:30-31, build-logic/convention/src/main/kotlin/com/vocabri/KoverConfiguration.kt:31-33, build-logic/convention/src/main/kotlin/KoverConventionPlugin.kt:26-30
Key Components
KoverConventionPlugin: A simple plugin that applies the Kover Gradle plugin usingpluginManager.apply(KoverGradlePlugin::class).
Sources: build-logic/convention/src/main/kotlin/KoverConventionPlugin.kt:26-30ProjectConventionPlugin: A broader convention plugin that appliesapplyKover()andapplyKoverExclusions()to each subproject, ensuring project-wide coverage configuration.
Sources: build-logic/convention/src/main/kotlin/ProjectConventionPlugin.kt:30-31libs.versions.toml: Defines the Kover plugin alias (kover) and version, which is used to apply the plugin in the build logic.
Sources: gradle/libs.versions.toml:17, gradle/libs.versions.toml:112
Configuration and Exclusions
To ensure that coverage reports are meaningful, certain types of code are excluded from the analysis. This includes UI code, generated files, and dependency injection modules, which are typically not suitable for unit testing or would skew coverage metrics. The configuration is centralized in KoverConfiguration.kt.
Sources: build-logic/convention/src/main/kotlin/com/vocabri/KoverConfiguration.kt:35-59
The core of the configuration is the coverageExclusions function:
// build-logic/convention/src/main/kotlin/com/vocabri/KoverConfiguration.kt
private fun KoverReportFiltersConfig.coverageExclusions() {
excludes {
androidGeneratedClasses()
annotatedBy(
"*ExcludeFromCoverage",
"*Composable",
"androidx.compose.ui.tooling.preview.Preview",
)
packages(
"com.vocabri.ui.theme",
"com.vocabri.ui.theme.*",
"com.vocabri.data.data",
"com.vocabri.data.db",
)
classes(
"*.BuildConfig",
"*.R",
"*.BR",
"android.*",
"*ComposableSingletons",
"*ComposableSingletons*",
"*ModuleKt",
)
}
}
Sources: build-logic/convention/src/main/kotlin/com/vocabri/KoverConfiguration.kt:41-62
Exclusion Rules Summary
The following table summarizes the patterns used to exclude files from code coverage reports.
| Exclusion Type | Pattern | Purpose |
|---|---|---|
| Annotation | *ExcludeFromCoverage | Excludes code marked with the custom ExcludeFromCoverage annotation. |
*Composable | Excludes Jetpack Compose UI functions. | |
androidx.compose.ui.tooling.preview.Preview | Excludes Jetpack Compose preview functions. | |
| Package | com.vocabri.ui.theme | Excludes the UI theme and styling code. |
com.vocabri.data.data | Excludes data model classes. | |
com.vocabri.data.db | Excludes generated SQLDelight database code. | |
| Class | *.BuildConfig, *.R, *.BR | Excludes Android-generated build and resource files. |
android.* | Excludes Android framework classes. | |
*ComposableSingletons* | Excludes generated classes for Compose singletons. | |
*ModuleKt | Excludes Koin dependency injection modules (e.g., AppModuleKt). |
Sources: build-logic/convention/src/main/kotlin/com/vocabri/KoverConfiguration.kt:45-59
The ExcludeFromCoverage Annotation
For cases where the standard exclusion rules are not sufficient, the project defines a custom annotation, @ExcludeFromCoverage, to manually mark code that should be ignored by Kover.
*Sources: domain/src/main/java/com/vocabri/domain/model/kover/ExcludeFromCoverage.kt
Definition
The annotation is defined to be applicable to classes, functions, properties, and entire files, with runtime retention.
// domain/src/main/java/com/vocabri/domain/model/kover/ExcludeFromCoverage.kt
package com.vocabri.domain.model.kover
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.FILE)
@Retention(AnnotationRetention.RUNTIME)
annotation class ExcludeFromCoverage
Sources: domain/src/main/java/com/vocabri/domain/model/kover/ExcludeFromCoverage.kt:24-26
This diagram shows the structure of the annotation.
Usage Example
This annotation is primarily used to exclude dependency injection modules, which consist of boilerplate code for object instantiation and are not logical candidates for unit testing.
// app/src/main/java/com/vocabri/di/AppModule.kt
@ExcludeFromCoverage
val appModule = module {
viewModelOf(::MainViewModel)
viewModelOf(::DictionaryViewModel)
// ...
}
Sources: app/src/main/java/com/vocabri/di/AppModule.kt:32-33, domain/src/main/java/com/vocabri/domain/di/DomainModule.kt:29-30
Running Coverage Reports
The project's README.md file provides instructions for generating coverage reports via Gradle tasks.
./gradlew koverHtmlReport: Generates an aggregated HTML report for all modules, which is easy to view in a browser../gradlew koverXmlReport: Generates an XML report, which is suitable for integration with CI/CD systems and other analysis tools like DeepSource.
These tasks are part of the recommended pre-pull-request checks to ensure code quality is maintained.
Sources: README.md:50, README.md:68
Summary
Kover is a deeply integrated quality tool in the Vocabri project, enforced through custom Gradle convention plugins. Its configuration is fine-tuned to exclude irrelevant code such as UI, generated files, and DI modules, providing accurate and actionable coverage metrics. The custom @ExcludeFromCoverage annotation offers additional flexibility for manual exclusions. By leveraging Kover, developers can effectively track test coverage and maintain a high standard of code quality across the application.