Summary#
Runs your app's tests against a Platform running on your own machine — no account, no network, no cloud. It is the local counterpart of Running tests: the same tests, the same throwaway-copy isolation, the same streamed report. The only difference is where it runs.
Signature#
osy test [path] [--filter <text>] [--test <id>] [--pixels] [--headed] [--json]Description#
Start a local platform, then test against it#
A local platform is a full Platform that runs on your machine, with a database it manages itself. Start one from your project directory:
osyrin devThe first start downloads a small database bundle once; after that it is up in seconds. It binds to your machine only — nothing outside can reach it — and it needs no account and no cloud project. Leave it running in a terminal.
In another terminal, run your tests against it:
osy testThat is the whole loop: edit your source, osy test, watch it turn green. There is nothing to log into and nothing to
deploy — osy test finds the running local platform for your project on its own, ensures your app exists there,
compiles the source on your disk into it, and runs your tests.
--pixels — the same tests, in a real browser#
osy test renders your pages in a headless DOM with no font engine and no compositor. That is what makes it fast
enough to run on every change, and it means the run is blind to layout: a control is "visible" whether it is on
its card, off it, or underneath something else.
osy test --pixels runs the same tests in a real browser instead. Nothing about your test file changes — the
same locators, the same refusals — but the geometric claims in Layout assertions — is it actually usable on screen? are actually judged, and
Ui.Shot("label") writes a PNG you can open.
osy test # behaviour, in seconds
osy test --pixels # the same tests, with layout checked and screenshots written
osy test --pixels --headed # …and show the browser, slowed down, so you can watch it driveIt is opt-in because it costs a browser: the tier needs Playwright and a Chromium, or the Chrome already on your machine, which it prefers. The check runs before anything is compiled or booted, so a machine that cannot run it is told in a second — with the command that fixes it — rather than a minute into a run.
The tests run exactly as they would anywhere#
Local is not a weaker mode. Your app's own security is enforced just as it is in production: a [Test] runs as an
anonymous, secured caller, so a test that creates or reads data needs your model to grant it — a plain new app is
secure by default. This is the same behavior described in Running tests; the point of running locally is
speed and privacy, never a relaxed rulebook. The starter model a new project ships with grants exactly what its first
test needs and nothing more.
Everything else is identical to a remote run: each [TestFixture] seeds its own private branch, each [Test] forks
its own throwaway clone, results stream back one at a time, and nothing a test writes survives it. See
Running tests for the full model.
Choosing what to run#
The same two ways as a remote run:
--filter <text>runs the tests whose names containtext.--test <id>runs exactly one test, named by its id (file::fixture::name). Repeat the flag for several.
A fixture is never filtered away, and a [Skip("reason")] test is always reported and never runs.
Scripting a run#
--json writes one JSON object per line, in the order events happen, so a script can react to each test as it lands.
The command exits non-zero when any test fails or errors, and diagnostics go to standard error — standard output stays
a clean stream of events. The event shape is the same as a remote run.
When there is no local platform#
If no local platform is running for your project, osy test says so and stops, rather than silently reaching
elsewhere:
No local platform is running for this project. Start one with `osyrin dev`.Run osyrin dev and try again.
Examples#
The two-terminal loop — one platform, many test runs:
# terminal 1
osyrin dev
# terminal 2
osy test
osy test --filter Totals
osy test --test "tests/orders.test.osy::Seeded::Totals_Add_Up"A first test in a freshly scaffolded project, which passes because the starter model grants it:
// model/note.osy
entity Note {
[Required] string Title;
security { allow read, create when IsAuthenticated || IsAnonymous; }
}// tests/note.test.osy
[Test]
void a_new_note_keeps_its_title() {
var note = new Note { Title = "First note" };
Assert.Equal("First note", note.Title);
}See also#
Running tests — the same run against a remote platform, and the full description of fixtures, isolation, and the streamed report.
Debugging tests locally — debug a single test locally with breakpoints and stepping in your editor.
Running a local platform — the local platform these tests run against, and how to start it.