Skip to content

Extension-gated Python tests never run in CI: no test job builds the Rust extension #258

Description

@leynos

Overview

The Python-side tests that exercise the compiled Rust extension are gated on
that extension being importable, and no CI job that runs the test suite builds
it. They therefore skip on every run, in every job, and have done since they
were written.

Evidence

maturin develop appears exactly once in .github/workflows/ci.yml, at
line 293, inside the benchmark-ratchet job — which runs benchmarks, not the
test suite:

$ grep -rn "maturin develop" .github/workflows/*.yml
.github/workflows/ci.yml:293:  UV_CACHE_DIR=.uv-cache UV_TOOL_DIR=.uv-tools uv run maturin develop \

The three jobs that do run tests — lint-test, typecheck-test, and
coverage — reach the suite through make build, which is only a dependency
sync:

build: uv .venv ## Build virtual-env and install deps
	$(UV_RUN_ENV) uv sync --group dev

So the extension is never present when the tests run.

Affected modules

Every module below is gated on the compiled extension and therefore skips:

  • cuprum/unittests/test_rust_streams.py
  • cuprum/unittests/test_rust_streams_boundary_property.py
  • cuprum/unittests/test_rust_extension.py
  • cuprum/unittests/test_rust_splice.py
  • cuprum/unittests/test_backend.py (the extension-dependent cases)

Why this matters

The skips are silent. A green CI run is indistinguishable from one in which
the entire Python/Rust boundary went unexercised, which is precisely the
boundary most likely to break: FD ownership, the GIL release, error
translation across the PyO3 edge, and the backend-selection fallback.

It also distorts review. PR #241 was asked to "add or unskip the required
Python/Rust boundary integration tests"; the tests already exist and are
already correct — nothing was skipped by omission. The defect is in the CI
wiring, not the test suite, and no amount of test authoring fixes it.

Proposal

Build the extension in the jobs that run the suite, then make the skip loud:

  1. Add a maturin develop --manifest-path rust/cuprum-rust/Cargo.toml step to
    lint-test (and coverage, if the coverage numbers should include the
    boundary), mirroring the invocation already proven in benchmark-ratchet.
    Consider a make develop target so local and CI use one definition.
  2. Add a CI-only guard that fails when the extension is unimportable — an
    environment variable such as CUPRUM_REQUIRE_RUST_EXTENSION=1 that turns
    the skip into an error. Without this, a future change that breaks the build
    step silently restores the present situation.
  3. Consider a job-summary line reporting how many extension-gated tests ran,
    so the count is visible rather than inferred.

Step 2 is the important one: the current failure mode is not "the tests are
missing" but "the tests report success without running".

Cost trade-off

Low to moderate — one build step per job, at the cost of Rust compilation time
on jobs that currently skip it. Worth measuring against the alternative, which
is a boundary that has never been tested in CI.


Raised from PR #241.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmediumRoadmap items to schedule within the current quarter. Clear scope, normal review cycles.testingTest coverage, test infrastructure, and verification tooling work.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions