android-jvm-test-coverage
Skill18 starsChanged 4 months agoMITView on GitHub
Measure JVM unit-test coverage for a module in a native Android Gradle project and print the Android-Studio-style report — the module total plus per-package and per-class Class/Method/Line/Branch percentages. Use this skill whenever the user wants test coverage for local JVM unit tests (the `src/test` suite, run via `testDebugUnitTest` or `test`), asks "what's the coverage of this module/package/ class", "how well is X tested", wants a coverage report without opening Android Studio, or wants the same numbers Android Studio's "Run with Coverage" gives but from the command line. Works on both Android library/app modules and pure Kotlin/JVM modules. This is for JVM unit tests, NOT on-device instrumented (androidTest) coverage.
In this repository67 other files it gives its agents.
- agent-onboardingSkill
- android-backgroundSkill
- android-cliSkill
- android-compose-architectureSkill
- android-compose-componentsSkill
- android-data-layerSkill
- android-di-koinSkill
- android-error-handlingSkill
- android-integration-testingSkill
- android-jacoco-setupSkill
- android-module-structureSkill
- android-navigationSkill
- android-presentation-mviSkill
- android-preview-figma-verifySkill
- android-ui-screenshot-verifySkill
- android-ui-testingSkill
- android-ui-verifySkill
- android-unit-testingSkill
- android-version-catalogSkill
- architecture-decision-recordSkill
- careful-planningSkill
- compose-adaptive-layoutsSkill
- figma-to-android-vectorSkill
- finalizeSkill
- git-commitSkill
- handoffSkill
- kmp-compose-architectureSkill
- kmp-compose-componentsSkill
- kmp-data-layerSkill
- kmp-di-koinSkill
- kmp-error-handlingSkill
- kmp-integration-testingSkill
- kmp-migration-analyzerSkill
- kmp-module-structureSkill
- kmp-navigationSkill
- kmp-presentation-mviSkill
- kmp-ui-testingSkill
- kmp-unit-testingSkill
- kotlin-coroutinesSkill
- kotlin-flowsSkill
- kotlin-mutation-testingSkill
- openspec-artifact-review-lightSkill
- openspec-artifact-reviewSkill
- project-breakdownSkill
- react-data-layerSkill
- react-error-handlingSkill
- react-integration-testingSkill
- react-presentation-mviSkill
- react-project-structureSkill
- react-routingSkill
- react-screen-architectureSkill
- react-securitySkill
- react-server-stateSkill
- react-ui-componentsSkill
- react-unit-testingSkill
- speckit-parallelize-agent-teamsSkill
- speckit-parallelize-subagentsSkill
- spring-api-layerSkill
- spring-di-configurationSkill
- spring-integration-testingSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 2 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 56
If you are *already* running inside a sub-agent, perform the steps directly: sub-agents cannot dispatch further sub-agents in Claude Code.
- Distinctive: line 70
add a "key findings", "gaps", or "what stands out" analysis section unless the user explicitly asks for interpretation.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Android JVM unit-test coverage
Produce the coverage report Android Studio shows for a JVM unit-test run — module total, per-package, and per-class Class / Method / Line / Branch percentages — straight from the command line, without modifying any committed build files.
How it works
./gradlew testDebugUnitTest produces no coverage on its own; Gradle has no
built-in coverage engine. This skill applies JaCoCo at runtime through a Gradle
init script. JaCoCo instruments the compiled bytecode in-process during the normal
JVM test run (no device, no androidTest) — the same engine AGP's
enableUnitTestCoverage uses internally.
Two bundled files do the work:
assets/jvm-coverage.init.gradle.kts— applied via--init-script. It is non-invasive: it touches nobuild.gradle.ktsand produces no git diff. It attaches JaCoCo to each module's unit-test task and registers ajvmCoveragetask that emits a JaCoCo XML report. It auto-selects the right test task (testDebugUnitTestfor Android modules,testfor pure Kotlin/JVM modules).scripts/render_coverage.py— parses that XML into the Android-Studio-style table.
Always run this in a sub-agent
A coverage run compiles the module, executes its tests, and emits a large amount of Gradle output before any number appears. None of that belongs in the main conversation. So dispatch the run to a single sub-agent and let it return only the finished coverage table(s).
Dispatch one general-purpose sub-agent and give it:
- the module Gradle path(s) and matching directory(ies) (see the table below),
- the absolute path to this skill's
assets/jvm-coverage.init.gradle.ktsandscripts/render_coverage.py, - the instruction: run steps 2–3 of the workflow, then return only the
rendered table(s) — and, if the Gradle run fails, the
BUILD FAILEDblock verbatim instead.
If you are already running inside a sub-agent, perform the steps directly: sub-agents cannot dispatch further sub-agents in Claude Code.
Presenting the result
The renderer's output is the report. When you relay the sub-agent's result to
the user, reproduce the rendered table verbatim inside a fenced code block so
its monospace column alignment (the Class … Method … Line … Branch … layout and
n/a cells) is preserved exactly as shown under "Output shape".
Do not:
- reformat the table into a Markdown table or any other layout,
- rename, reorder, or merge columns,
- add a "key findings", "gaps", or "what stands out" analysis section unless the user explicitly asks for interpretation.
Report the numbers as produced; if the user wants analysis, they will ask.
Workflow
Let SKILL_DIR be this skill's directory. Run all Gradle commands from the project
root (where gradlew lives).
1. Identify the module
Map what the user named to a Gradle module path and its directory:
| Gradle path | Directory | Type |
:core:domain | core/domain | pure Kotlin |
:core:crypto | core/crypto | Android lib |
:feature:auth:data | feature/auth/data | Android lib |
(The init script handles the Android-vs-Kotlin difference automatically; you only need the path and directory.)
2. Run the coverage task
./gradlew :core:crypto:jvmCoverage \
--init-script "$SKILL_DIR/assets/jvm-coverage.init.gradle.kts"The XML lands at <module-dir>/build/reports/jvm-coverage/coverage.xml.
To cover every module in one pass, run the task unqualified — Gradle invokes it on each subproject that registered it:
./gradlew jvmCoverage \
--init-script "$SKILL_DIR/assets/jvm-coverage.init.gradle.kts"3. Render the report
python3 "$SKILL_DIR/scripts/render_coverage.py" \
core/crypto/build/reports/jvm-coverage/coverage.xml \
--module :core:cryptoFor a whole-project run, call the script once per module's XML (loop over the
coverage.xml files under each module's build/reports/jvm-coverage/).
To focus the per-class detail on one package, add --package (repeatable); the
module total still reflects the whole module:
python3 "$SKILL_DIR/scripts/render_coverage.py" \
core/crypto/build/reports/jvm-coverage/coverage.xml \
--module :core:crypto --package com.example.core.crypto.internalOutput shape
MODULE :core:crypto — Class 90% Method 82% Line 78% Branch 64%
com.example.core.crypto
Class 88% Method 80% Line 76% Branch 61%
AesGcm Class 100% Method 90% Line 85% Branch 70%
Sha256 Class 100% Method 100% Line 100% Branch n/a
com.example.core.crypto.internal
Class 100% Method 100% Line 95% Branch 80%
CharArrayUtf8 Class 100% Method 100% Line 95% Branch 80%n/a means JaCoCo emitted no counter of that kind for the node (e.g. a class with
no branches has no Branch %), exactly as Android Studio leaves such cells blank.
Notes
- Generated code is excluded to match what Android Studio treats as "your
code":
R/BuildConfig/Manifest, DI factories,di/packages, ComposeComposableSingletons, andkotlinx.serialization$$serializerclasses. Adjust thecoverageExcludeslist in the init script if a project needs different rules. - No coverage rows? Confirm the module actually has a
src/testsuite. Modules with onlysrc/androidTesthave no JVM unit tests and produce an empty report — this skill does not cover on-device instrumented tests. - Robolectric modules (e.g. those with
unitTests.isIncludeAndroidResources = true) work unchanged — their unit tests still run on the JVM. - The init script and XML live under
build/, which is git-ignored, so running the skill never dirties the working tree.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

