build: make ./gradlew test cover the KMP modules, and close two coverage gaps

The Kotlin Multiplatform plugin registers no plain `test` task - it creates one
per target (jvmTest, androidUnitTest, linuxX64Test, ...) plus `allTests`. A root
`./gradlew test` runs `test` only in projects that own one and silently skips the
rest; Gradle errors only when no project at all has the task, and the Java/Android
modules do, so it exited 0 looking healthy while never running quartz, commons,
commonsUI, quic, nestsClient or marmotQuic - about 8k of the ~11.7k tests here.

- Root build registers a `test` alias onto `jvmTest` for every KMP subproject.
  `./gradlew test` now runs 11,690 tests across 11 modules instead of 3,567
  across 5. It maps to jvmTest rather than allTests deliberately: allTests also
  pulls androidUnitTest and native targets that cannot run on a given host.
- CI (build.yml) gains :quic:jvmTest and :marmotQuic:jvmTest. Neither appeared in
  any workflow - `grep -rn quic .github/workflows/` returned nothing - so quic's
  495 RFC-vector and adversarial tests for the hand-rolled QUIC/TLS stack were
  running in no CI job at all.
- The pre-push hook gains :commonsUI:jvmTest and :marmotQuic:jvmTest, which it
  had never listed. It stays an explicit list rather than calling `./gradlew
  test`: a bare `test` would pull in :desktopApp:test, which needs a display
  server and is skipped on CLAUDE_CODE_REMOTE.
- CLAUDE.md documented `./gradlew test` as the way to run tests; it now says what
  that covers and how to name a single KMP module's suite.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nxd2uiYajDGuymQK93txzG
This commit is contained in:
Claude
2026-09-18 21:09:02 +00:00
parent a52ad0f2c3
commit 91b9e29588
4 changed files with 45 additions and 4 deletions
+6 -1
View File
@@ -224,9 +224,14 @@ version. `quartz/` is protocol-only — no composables.
# Build Quartz for all targets
./gradlew :quartz:build
# Run tests
# Run tests (every module, including the KMP ones)
./gradlew test
# One module. KMP modules (quartz, commons, commonsUI, quic, nestsClient,
# marmotQuic) have no `test` task of their own - the root build registers an
# alias onto jvmTest, which is the task to name directly:
./gradlew :quartz:jvmTest --tests "com.vitorpamplona.quartz.nip52Calendar.*"
# Format code
./gradlew spotlessApply
```
+10
View File
@@ -16,11 +16,21 @@ echo "Running test... "
# variants of :amethyst (play/fdroid × debug/release/benchmark) plus full
# native-libs merging per variant — ~6× the work of one variant. CI runs the
# multi-flavor matrix on push to main; pre-push only needs one happy path.
#
# Every KMP module's tests live under <module>:jvmTest - the Kotlin Multiplatform
# plugin registers no plain `test` task - so a module missing from this list is a
# module nobody runs before pushing. Add new KMP modules here when they gain tests.
#
# `./gradlew test` now reaches the KMP modules too (see the `test` alias in the root
# build), but this hook stays explicit: a bare `test` would also pull in :desktopApp:test,
# which needs a display server and is deliberately skipped on CLAUDE_CODE_REMOTE below.
TASKS=(
:quartz:jvmTest
:commons:jvmTest
:commonsUI:jvmTest
:nestsClient:jvmTest
:quic:jvmTest
:marmotQuic:jvmTest
:amethyst:testPlayDebugUnitTest
:cli:test
)
+4 -3
View File
@@ -102,15 +102,16 @@ jobs:
- name: Test + Build Desktop (gradle)
run: |
CMD="./gradlew :quartz:jvmTest :commons:jvmTest :commonsUI:jvmTest :nestsClient:jvmTest :cli:test :desktopApp:test :desktopApp:${{ matrix.desktop-task }}"
CMD="./gradlew :quartz:jvmTest :commons:jvmTest :commonsUI:jvmTest :quic:jvmTest :nestsClient:jvmTest :marmotQuic:jvmTest :cli:test :desktopApp:test :desktopApp:${{ matrix.desktop-task }}"
if [ "${{ runner.os }}" = "Linux" ]; then
xvfb-run --auto-servernum $CMD
else
$CMD
fi
# This job runs five test suites (:quartz, :commons, :nestsClient, :cli,
# :desktopApp) but, unlike test-geode / test-quartz-ios /
# This job runs the JVM test suites (:quartz, :commons, :commonsUI, :quic,
# :nestsClient, :marmotQuic, :cli, :desktopApp) but, unlike test-geode /
# test-quartz-ios /
# test-and-build-android, published nothing when one of them failed. The
# console line names the failing test and the exception class and stops
# there, so the message is lost with the runner. That is how the
+25
View File
@@ -91,6 +91,31 @@ allprojects {
subprojects {
afterEvaluate {
// The Kotlin Multiplatform plugin never registers a plain `test` task: it creates one
// task per target (jvmTest, androidUnitTest, linuxX64Test, ...) plus the `allTests`
// aggregate. A root `./gradlew test` therefore runs `test` only in the Java/Android
// modules that own one and *silently* skips every KMP module - Gradle only errors when
// no project at all has the task, and four of them do, so it exits 0 looking healthy.
// That hid ~8k tests (quartz, commons, commonsUI, quic, nestsClient, marmotQuic), which
// is most of this repo's suite. Register the alias so the documented command means what
// it says.
//
// It maps to jvmTest, not allTests, on purpose: allTests also drags in androidUnitTest
// and the native targets, half of which cannot run on a given host (macosArm64Test on
// Linux) and all of which change what `test` costs. jvmTest is exactly what the
// pre-push hook and CI already run for these modules, so the alias matches the coverage
// they expect rather than inventing a third definition of "the tests".
if (plugins.hasPlugin("org.jetbrains.kotlin.multiplatform") &&
tasks.findByName("test") == null &&
tasks.findByName("jvmTest") != null
) {
tasks.register("test") {
group = "verification"
description = "Runs the JVM unit tests for this Kotlin Multiplatform module."
dependsOn("jvmTest")
}
}
try {
tasks.named("preBuild") {
dependsOn("spotlessApply")