-
Notifications
You must be signed in to change notification settings - Fork 2
coverage
title: "Coverage" description: "Kover-based test coverage setup + the worker-kmp 100%-coverage gate for cmp-worker-* modules."
worker-kmp uses kotlinx-kover for line-coverage measurement + enforcement. Since v3.1.3, 8 testable commonMain modules carry a hard 100% line-coverage floor; CI fails PRs that regress below it.
# Generate aggregate HTML report
./gradlew koverHtmlReport
open build/reports/kover/html/index.html # macOS
# Generate XML report (CI / codecov consumption)
./gradlew koverXmlReport
# Verify 100% line coverage per opted-in module (fails on regression)
./gradlew koverVerifyKover instruments JVM bytecode only. KMP commonMain code compiles to JVM (via jvmTest)
so it IS measured. iOS, JS, and wasmJs platform actuals do NOT get coverage — see the exclusions
below.
| Module | Status |
|---|---|
cmp-worker-kmp |
100% commonMain (gated by koverVerify) |
cmp-worker-store5 |
100% commonMain (gated by koverVerify) |
cmp-worker-storeflow |
100% commonMain (gated by koverVerify) |
cmp-worker-koin |
100% commonMain (gated by koverVerify) |
cmp-worker-sync |
100% commonMain (gated by koverVerify) |
cmp-worker-test |
100% commonMain (gated by koverVerify) |
cmp-worker-scheduler |
100% commonMain (gated by koverVerify) |
cmp-worker-compose |
100% commonMain (gated by koverVerify; @Composable bodies filter-excluded per exclusion patterns) |
| Module | Why excluded |
|---|---|
cmp-worker-app-annotations |
Annotation-only module — no executable code to measure. |
cmp-worker-android, cmp-worker-ios, cmp-worker-desktop, cmp-worker-desktop-daemon, cmp-worker-web, cmp-worker-web-push
|
Platform actuals; Kover only measures JVM bytecode. Tracked separately by the Tier-2 follow-up epic worker-kmp-platform-engine-tests, which adds Robolectric (Android) + Xcode-sim (iOS) + browser-test (Web) harnesses. |
cmp-worker-app-ksp, cmp-worker-app-plugin
|
Build-tooling (KSP processor + Gradle plugin) — needs Gradle TestKit; deferred. |
cmp-worker-bench, cmp-worker-migrate
|
Non-production tooling. |
samples/* |
Illustrative; not under coverage threshold. |
The root KoverConventionPlugin
delegates to configureKoverRootReports() in
Kover.kt,
which excludes:
excludes {
classes(
"*.di.*", // Koin DI declarations
"*.BuildConfig", // Android-generated BuildConfig
"*ComposableSingletons*", // Compose generated lambda holders
"*_*Factory*", // Generated factories
"*\$ComposableLambda\$*",
"*Preview*", // @Preview functions
"*Test*", // Test helpers themselves
)
packages(
"*.generated.*",
"*.ksp.*",
"*.android", "*.ios", "*.jvm", "*.js", "*.wasmJs", // platform actuals
)
annotatedBy("androidx.compose.runtime.Composable")
}The verify rule enforces:
verify {
rule { minBound(100) }
}This is LINE aggregation per the Kover default; per-module — each opted-in module
gates its own bytecode.
- Add
id("io.github.mobilebytelabs.kover")to the new module'sbuild.gradle.ktsplugins {}block. - The convention plugin auto-registers it with the root aggregator via
rootProject.dependencies.add("kover", project). -
./gradlew :{new-module}:koverVerifywill start failing until 100% line coverage is reached. - If the new module is platform-heavy (mostly
androidMain/iosMain/ etc.), do NOT apply the plugin — add a row to the "Modules NOT in scope" table above and surface the gap in the Tier-2 follow-up epic.
For provably-uncoverable lines (e.g. sealed when synthetic else branches that the bytecode
verifier mis-counts as missed), two options:
-
Per-class exclusion — extend the
classes(...)list inKover.ktwith the FQN. Document the reason in a code comment. -
@ExcludeFromCoverage(future) — once the marker annotation lands, annotate the uncoverable member and reference it via the filter'sannotatedBy(...).
Every escape hatch must carry a code-comment rationale and a linked issue. The quarterly maintenance pass prunes stale exclusions.
The Test Coverage / Kover 100% gate job at
.github/workflows/test-coverage.yml runs on every
PR + push to main / development. It:
- Runs
./gradlew koverHtmlReport koverXmlReport koverVerify. - Uploads the aggregate HTML report as
kover-html-report(14-day retention). - Posts the aggregate
%to the PR Step Summary.
koverVerify exit ≠ 0 fails the PR. There is no soft-warn mode.
- Coverage epic plan:
plan-layer/project-plans/mbs/worker-kmp/archive/2026-06/kover-100-coverage/ - Tier-2 platform-engine tests:
worker-kmp-platform-engine-tests - Convention plugin pattern:
convention-plugin.md
Getting Started
Platform Support
Features
Operations
Release