Skip to content

Tests that early-return on an unsupported platform report as PASSED, so the executed count overstates coverage #261

Description

@monkopedia-coder

RpcFunctionalityTest is a shared base used by 20 test classes. Each of its five tests opens with a guard that returns before doing anything:

@Test
fun testSerializePassthrough() = runBlockingUnit {
    if (TestType.SERIALIZE !in supportedTypes) return@runBlockingUnit
    …
}

testPipePassthrough, testHttpPassthrough, testWebsocketPassthrough and testServiceWorkerPassthrough have the same shape (RpcFunctionalityTest.kt:73, 89, 132, 173, 203).

A test that returns early reports as PASSED, not skipped. It contributes a green line and a tests="1" to the XML while asserting nothing. So the executed count — the number this repo has been leaning on all evening to distinguish "ran" from "did not run" — overstates coverage here, and no amount of checking that a task ran, or that a filter matched, or that results are fresh will reveal it.

The guard set differs per platform (platformSupportedTestTypes()):

platform supported so these no-op and pass
jvm all but SERVICE_WORKER 1 of 5
native SERIALIZE, PIPE, HTTP 2 of 5 (WEBSOCKET, SERVICE_WORKER)
js / wasmJs SERIALIZE, PIPE, + SERVICE_WORKER only if (hasWindow()) 2 or 3 of 5

Across 20 classes that is a large number of green test lines that ran no assertions, and the count varies by platform in a way nothing reports.

Worth being clear about what is and is not wrong here. The mechanism is legitimate — a websocket test genuinely cannot run on a platform with no websocket support, and the alternative of duplicating the class per platform is worse. The defect is that skipping is indistinguishable from passing in the output. kotlin.test has no portable assumption/skip primitive, which is presumably why it was written this way.

Options, none free:

  • Have the guard fail rather than return when a type is unsupported and the platform claims to support it — catching the case where platformSupportedTestTypes() drifts out of date and quietly disables a test that should run.
  • Emit a marker (a log line, or a deliberate expected skip mechanism per platform) so a reader can count no-ops.
  • Split the class so each platform's test set is what it actually runs, at the cost of the duplication the base class exists to avoid.

Concrete instance worth resolving first, since it is measured rather than hypothetical: the js suite executed 383 tests on my machine and 379 on a GitHub runner (PR #259), same code. Four tests were not merely no-ops but were not generated at all. hasWindow() differing between a local headless Chromium and the runner's is the obvious candidate, and it means the js suite's SERVICE_WORKER coverage depends on which machine ran it — invisibly, because the missing tests were never counted and the no-op ones passed.

Found by applying sdbus's #227 finding (a suite reporting 7 passing tests with its dependency absent) to this repo.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent-workableClear, scoped, no user-judgment needed; triage dispatches work_on_issuebugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions