Why a formatter/orchestrator, not an interpreter¶
Minitest does two very different kinds of work, and only one of them needs a Ruby interpreter.
The deterministic core¶
Most of what makes Minitest Minitest is wording and bookkeeping:
- the exact failure message each assertion produces —
assert_equal'sExpected: 1\n Actual: 2diff form,assert_includes'sExpected [1, 2] to include 3., themu_ppinspection, the custom-message prepend, theassert_sameoid=diagnostic; - the run orchestration —
before_setup/setup/after_setup→ the body →before_teardown/teardown/after_teardown, with the setup+body sharing onecapture_exceptionsand each teardown getting its own; - result coding —
./F/E/S,passed?/skipped?/error?,location,Result#to_s; - mock bookkeeping — expectation queues, arity/args/kwargs matching, and the
MockExpectationErrorwording.
None of that evaluates Ruby. It is pure string formatting, control flow and data structures — so it lives here as pure Go, deterministic and reproducible, byte-for-byte identical to the gem.
The interpreter surface (a seam)¶
Everything that needs genuine Ruby object semantics is funnelled through one
explicit interface, Runtime:
- value inspection (
#inspect), equality (#==), identity (#equal?/object_id), regexp match (#=~),#respond_to?,#include?,#empty?,#nil?,#instance_of?/#kind_of?, class name, truthiness, and arbitrary#__send__for operator / predicate assertions.
The IO captured by assert_output / assert_silent and the execution of test
method bodies and assertion blocks are also seams — the host wires those
to the Ruby VM.
This library never evaluates Ruby. It only formats, orchestrates, and aggregates.
Why the split matters¶
Because the core is pure and interpreter-free, it:
- cross-compiles trivially and runs on all six 64-bit Go targets with no C toolchain;
- can be differentially tested against the real gem without embedding Ruby — the deterministic tests alone hold coverage at 100%, so the qemu cross-arch and Windows lanes pass the gate even where no Ruby is present;
- is reusable: a host such as rbgo implements the
Runtimeseam over its own object graph and gets gem-identical Minitest behavior, while any other Go program can import the assertion/lifecycle logic directly.
The dependency arrow points from go-embedded-ruby to this library, never the other way.