Data Nexus

Infrastructure · We run it ourselves

Vitest

A test runner that reuses the project's own Vite build configuration, so tests run through the same transform and the same module graph as the application.

Most suites are written to raise a number. The question worth asking of any test is which production failure it would have caught, and in the two repositories where we run Vitest that question deletes most of what a coverage target would have demanded. What survives it is a short list of tests that are genuinely load-bearing, plus an explicit decision about which parts are instrumented at runtime instead.

vitest.dev

01/Why this one

  1. 01

    The runner uses the project's own build configuration rather than a second toolchain maintained in parallel. In pakibus the TypeScript settings, the path resolution and the plugins that build the game are the ones the tests run through, so a test cannot pass because it was compiled differently from the thing it claims to test — which is the most tedious class of false confidence in a setup where the bundler and the runner each have their own opinion about modules.


  2. 02

    The tests worth writing are the ones covering silent failures. A crash announces itself and gets fixed without a suite. A throttler that lets one burst through announces itself hours later as a rate limit or a disconnected number, on a channel that cannot be replayed and where the evidence is a message that was never delivered. That asymmetry, not a line count, is what decides where a test goes in a bot that speaks over Telegram and WhatsApp.


  3. 03

    A test that mocks the dependency it is exercising asserts the mock. Checking that our code sends the request it was written to send verifies the author's memory of an interface, not the interface — so the model call and the messaging socket are boundaries we test on our side of, in what we parse and what we do with a malformed or unexpected payload, and not by simulating the far end.


  4. 04

    Coverage is only readable in one direction. A file at zero is a fact worth acting on. A project at eighty-five per cent is a number with no content, because V8 counts lines the process executed and an executed line has not been checked by anything. Set as a target it reliably produces tests that call every export, assert nothing, and then have to be maintained for the life of the code.


  5. 05

    Speed is a correctness property, not a convenience. Vitest re-runs from the module graph, so changing a file re-runs only the tests that import it transitively, and the loop stays short enough that the suite is used during the work rather than at the end of it. A suite long enough to justify a coffee is a suite that gets skipped, and a skipped suite is worse than no suite because it still claims to cover something.


  6. 06

    In a WebGL game the division is unusually sharp. Nothing about how a frame looks can be asserted; everything about the arithmetic behind it can. Vector maths, collision predicates and the state machine deciding what happens on a hit are deterministic and cheap to cover. The post-processing pipeline and the frame budget are judged by a frame monitor at runtime instead. Assert what is deterministic, instrument what is not, and do not write a snapshot test to pretend the second category belongs in the first.


  7. 07

    The same reasoning is why this site carries no Vitest suite at all. Its invariants are corpus invariants — a dangling @id in the structured data, a route and its Markdown twin disagreeing about what exists — and those belong in the build, where failing one stops a deployment, rather than in a runner somebody has to remember to invoke.

02/What you can check

An entry that cannot point at something you can open, run or read does not compile. That is a property of the type, not a promise in a paragraph.

In our code
openclaw/package.json — vitest with @vitest/coverage-v8, sitting alongside grammy with its throttling transformer and a WhatsApp socket library — the pipeline where a defect surfaces as an undelivered message rather than as a stack trace.

In our code
pakibus/package.json — vitest and vite in the same project as three, the post-processing pipeline and a frame monitor: the deterministic half under test, the rendered half under instrumentation.

Property of the thing
V8 coverage records which lines the process executed, not which behaviours were checked. A test file that imports a module, calls every export and asserts nothing produces the same coverage figure as one that verifies every return value. — Write both versions of the same test file, run the runner with coverage enabled twice, and compare the two reports.

Run it yourself
npx vitest related src/some-file.ts → Only the test files whose module graph reaches that file are executed; the rest are not run at all, which is the same graph the build uses.

In our code
scripts/check-schema.ts, scripts/check-markdown.ts, scripts/check-knowledge.ts — This site's invariants enforced as build gates that run before next build rather than as a unit suite — the deliberate absence of Vitest in a repository that could easily have carried it.
03/Where it stops

Invariant

Vitest runs in Node, with the DOM simulated when a test asks for one, and neither of these repositories fails there. The game breaks on a mid-range phone through a lost WebGL context, a thermal ceiling and a GPU memory budget that no runner on a workstation reproduces. The messaging socket breaks when the far side changes behaviour without notice, which a mocked socket cannot detect because the mock encodes what the protocol did on the day it was written. Nearly everything expensive in both projects fails outside the suite, so a green run is evidence that the logic we chose to encode still holds — and nothing more than that.