Run a scenario
Open a scenario and click Run (headless) or Debug (visible browser + pause on breakpoints and failure). A run tab opens immediately and updates live.
Live streaming
Results stream over WebSocket as each step executes — no waiting for the whole run to finish. Step status updates in place: pending → running → passed/failed.
Block view
The scenario renders as a block view: each step("…") is a foldable group,
each DSL call a row with a status icon, line number and duration. Fold a step to
see intent; unfold to see the calls.
Trace: the execution tree
The run header offers three views: Steps (the test’s source, with
the run projected onto it), Trace (since 0.31.0) and Code. Trace
is built from the run journal alone and follows what actually ran: a
statement that calls a helper opens into the helper’s own statements and
step(...) blocks (the file is named at the right of the row), a loop
opens into one group per iteration — including an iteration that ran no
statement — and a step(...) block into its envelope with its tag and
duration. Helper calls and passed iterations start folded with a summary
(“10 iterations · 1 failed”); the failed branch is open down to the
failing statement, which carries the error card. Double-click a row to
open its file at that line in Code — a helper file too. Notes, log lines
and verdicts sit under the statement that produced them, as in Steps;
screenshots open from the row, helper-frame captures included. The view
you pick is remembered; a debug session always opens in Code. Runs
recorded before 0.31.0 have no iteration markers: a loop body then reads
flat under the loop. The inspector’s flat event list is the Events
tab.
Notes, log lines and verdicts
A step that called note(label, value), log(...) or assertJudge(...)
shows an ⓘ N chip on its row (since 0.31.0). Click it to open the list
under the step: notes as label → value, log lines, and the judge’s
verdict as judge ✓/✗ · rubric · text. The list opens by itself under a
failed step and under a verdict that said no; what you open or close is
remembered per scenario and step. A failed judge step’s error card
carries the whole verdict — rubric, judged text, reasoning, model. After
the run, the System pane lists the scenario’s log(...) lines with
their time.
Step screenshots
With UNOTEST_STEP_SCREENSHOTS=1 the runner captures a PNG after every step
(details). Step rows with a capture show a
camera icon — click to open the frame full-screen and step through the run
visually. screenshot() DSL captures appear the same way.
Error cards
When a step fails, an inline error card pins to the offending line — the
error class, message, and the file:line source snippet — so you see exactly
what broke without scrolling away.
Collections
Run a whole collection from its view. You get a per-scenario status list, a progress bar, and a one-click abort that stops all in-flight scenarios.
The run queue
Runs of one project and environment go through a queue, so a run started
from the CLI, from the Run button and by an agent cannot drive the same
browser and the same seeded database at once. The queue serialises runs, not
scenarios: a collection’s workers still run in parallel under their
parent’s slot. queue.concurrency in unotest.config sets how many runs may
be in flight for one environment (1 by default — strict FIFO);
queue.enabled: false turns the queue off for the project,
UNOTEST_NO_QUEUE=1 for a single command. A CLI run that has to wait says so
(queued behind N run(s) — waiting for a free slot), and Ctrl-C gives up its
place in line. The Active section lists the runs waiting for a slot
(queued · 1/1 slot busy), each with the kind of producer that queued it
(cli, viewer, an agent) and since when, with a ✕ that takes a run out of
the queue.
Schedule…
Right-click a scenario or a collection → Schedule… (once set, the item
reads Schedule · daily at 03:00, Schedule · every 5 min, Schedule · hourly at :30, Schedule · Mon, Wed at 03:00 and the like). The popup is a
small builder, not a cron field: pick a frequency — not set, every 5 minutes … every 12 hours, every day, every week — and the minutes,
hours and days it applies to, optionally an env. Under it a caption shows
the next tick and the cron it produces: next: tomorrow 03:00 · your clock cron: 0 3 * * *. The time is your browser’s clock; the box that executes
the schedule usually ticks in UTC. Saving writes unotest/schedules.yaml; an entry
declared in unotest.config is shown read-only (Declared in unotest.config — edit it there), and on a deployed tree (a box) every schedule is
read-only. On Home, flip last run | schedule: tiles are tinted by
frequency (brighter = more often, grey = not scheduled), the counters
become scenarios / scheduled / no schedule filters, and an upcoming list orders the next
ticks on your clock. Nothing in the viewer ticks — the schedules are
declarations for the box or the CI that hosts your runs.