std.testing — compiler internals¶
This page documents the internal integration model, runtime boundary design, and open design questions for the
std.testing stdlib module. It is aimed at compiler contributors, not Incan users.
For the user-facing guide, see [Language → How-to →
std.testingguide]. For the API reference, see Language → Reference → Testing.
Integration model (RFC 023 Phase 5)¶
std.testing is compiled from Incan source instead of relying on hardcoded Rust assertion helpers.
- Source of truth:
crates/incan_stdlib/stdlib/testing.incn. - Rust module mapping: the file declares
rust.module("incan_stdlib::testing"), routing host-boundary calls to theincan_stdlib::testingRust module. - Incan-implemented assertions:
assert,assert_eq,assert_ne,assert_true,assert_false,assert_is_some,assert_is_none,assert_is_ok,assert_is_errare all written in Incan source. They delegate tofail()/fail_t()for the actual panic. - Host-boundary primitives (
@rust.extern):fail(msg)/fail_t[T](msg)— panic primitives implemented inincan_stdlib::testing.assert_raises— not yet implemented (FIXME in stdlib source).- Marker entrypoints (
skip,xfail,slow,fixture,parametrize) — their Rust implementations intentionally panic with a "runtime misuse" message; they exist only to satisfy the extern boundary.
- Marker metadata: each marker extern carries
metadata={...}on its@rust.externannotation.incan testreads this metadata from the parsed stdlib source (viasrc/frontend/testing_markers.rs) as the single source of truth for marker semantics. - Surface semantics routing:
- Pack contracts live in
crates/incan_semantics_core(SurfaceFeatureKey, pack trait, registry). - Stdlib handlers live in
crates/incan_semantics_stdliband are feature-gated bystd_testing. - Frontend/back adapters call into the registry (
src/frontend/surface_semantics.rsandsrc/backend/ir/surface_semantics.rs). assertstatement syntax is lowered through registry-provided canonical call target metadata.- Lowered assert calls carry canonical callee paths (
std.testing.assert_*) in IR. - Emission uses canonical paths for stdlib dispatch, so
import std.testingandfrom std.testing import assert_*behave consistently.
- Pack contracts live in
This design keeps user-facing assertion behavior in one stdlib Incan file while limiting Rust host code to unavoidable panic/failure primitives.
Runtime boundary shape¶
The runtime boundary is intentionally narrow:
- Incan-first assertions: behavior lives in
testing.incn, not duplicated Rust wrappers. Adding a new assertion helper means editing Incan source, not touchingincan_stdlib::testing. - Host orchestration for markers: discovery and execution semantics (
skip,xfail,slow, fixtures, parametrize) are resolved byincan testfrom stdlib metadata at discovery time — they are never invoked at runtime in normal test execution. - Fail-fast on runtime misuse: the Rust marker stubs panic immediately with a clear message if a marker function is ever called outside the test runner (e.g., used as a regular function call instead of a decorator).
Marker metadata flow¶
crates/incan_stdlib/stdlib/testing.incn src/frontend/testing_markers.rs
┌──────────────────────────┐ ┌──────────────────────────────┐
│ @rust.extern(metadata={ │ parse │ TestingMarkerSemantics │
│ "marker_kind": "skip", │ ───────► │ ├ markers: { skip, xfail, │
│ "runner_only": true │ │ │ slow, fixture, │
│ }) │ │ │ parametrize } │
│ pub def skip(...) │ │ └ metadata per marker │
└──────────────────────────┘ └──────────────┬───────────────┘
│
src/cli/test_runner/discovery.rs
│
┌──────────────▼───────────────┐
│ resolve decorator → marker │
│ apply skip/xfail/slow/etc. │
└──────────────────────────────┘
Key files:
| File | Role |
|---|---|
crates/incan_stdlib/stdlib/testing.incn |
Canonical stdlib source (assertions + marker decls) |
crates/incan_stdlib/src/testing.rs |
Rust host-boundary implementations (panic stubs) |
src/frontend/testing_markers.rs |
Parses marker metadata from stdlib; cached via OnceLock |
src/cli/test_runner/discovery.rs |
Consumes marker semantics for test discovery |