Assertions
On this page
assert condition fails the test when the condition is false. On failure,
the report shows the file, the line, the source of the condition, and the
value of each side of a comparison.
Checking that a call fails
To check that a call fails, name the failure with fails:
test "completing a missing todo fails" { var alice: Principal.user = alice_with_todos() var missing: Todo.id = "01908f6e-1c2a-7b3c-9d4e-5f6a7b8c9d0e" assert complete_todo(missing, alice) fails TodoNotFound}
assert … fails checks the call itself. A failure that leaves while the
call's arguments are worked out ends the test, like any other unhandled
failure.
Calls that can fail
A call that can fail still needs attempt, match or assert … fails,
as everywhere else
(Passing a failure on: attempt).
A call with attempt that fails ends the test as failed, and names the
failure.
Comparing values
Whole values are compared with ==. On failure, records and lists show a
field-by-field diff. A route test checks response.status,
response.code and the typed output (Route tests).
There are no snapshot assertions, and no mocks of your own code.
Events and query cost
assert emitted ReminderDue { todo_id: todo.id } checks that an event
was emitted, as the fakes' .requests checks provider calls. It isn't
built yet.
A test doesn't assert what a query costs. The compiler reports each query's cost in the build report, and a change shows in the approval review.
What a failed test reports
A failed test gives a person or an agent everything needed to fix it
without rerunning it, the same standard as the application's own
failures. It is shown readably in a terminal, and as
versioned JSON with --json:
FAIL a rate-limited reminder is retried domains/planning/schedules/overdue_reminders.test.jadpo:31 assert list.count(sent) == 2 │ │ 1 [ReminderMessage { to: "alice@example.test", todo_title: "Buy milk", ... }] expected 2 actual 1 what ran (trace t-7f3a, clock 2026-01-15T12:00:00Z, order seed 48213): overdue_reminders.run() 2 todos due queue_overdue_reminders() committed: 2 Todo updated, 2 ReminderDue emitted send_reminder (ReminderDue todo=01908f6e…) reminders.messages.send → rate_limited → retry send_reminder (ReminderDue todo=01908f6e…) retry scheduled for 12:00:02, not yet due send_reminder (ReminderDue todo=7c21d0aa…) reminders.messages.send → accepted fakes: reminders.messages.send 2 scripted, 2 used data: kept as jadpo_test_7f3a (--keep-failed) rerun: jadpo test domains/planning/schedules/overdue_reminders.test.jadpo:31 --seed 48213
- The assertion broken into parts: every sub-expression's value, with records compared field by field in a diff.
- For
assert … fails X: the failure that happened instead, with its internal fields, or the value the call returned. - What ran: the test's trace in short (Debugging and review): actions, queries, writes, events delivered or pending, retries, and provider calls with what was sent and answered.
- How to reproduce it: the clock, the order seed, configuration overrides, fake usage, the kept database and the exact rerun command.
- Every failure has a stable code (
test.assertion_failed,test.fake_unused,test.fake_exhausted,test.unexpected_failure,test.faultfor a fault such as an overflow, andtest.subscriber_failedfor a subscriber's delivery that failed for good between the test's steps) so an agent can act on it without parsing text. Each is shown with its real report under Errors.
As JSON
jadpo test --json prints one document in the envelope every command
shares (schemaVersion 2, command, ok, data, diagnostics), and
jadpo help --json describes every field under testReport. data holds the order seed; root, the project folder as
seen from where the command ran ("." from inside it), which every path is
relative to; the selection; the counts; and the tests in the order
they ran. A failed test's failure has its code and help, its
location in the test, one of assertion, failure or fault, for
test.subscriber_failed the delivery it happened in (its event,
subscriber, attempt and attempts, null otherwise), and the
rerun command, which works from where the command ran. Part of the
document for the test.fault example under Errors:
{ "code": "test.fault", "location": { "path": "plans.test.jadpo", "start": 93, "end": 117, "line": 3, "column": 12, "endLine": 3, "endColumn": 36, "label": "" }, "fault": { "kind": "int_overflow", "at": { "path": "plans.jadpo", "start": 118, "end": 134, "line": 6, "column": 19, "endLine": 6, "endColumn": 35, "label": "out of range" }, "stack": [ { "location": { "path": "plans.jadpo", "start": 118, "end": 134, "line": 6, "column": 19, "endLine": 6, "endColumn": 35, "label": "" }, "callable": "function plan_effort", "repeats": 1 }, { "location": { "path": "plans.test.jadpo", "start": 93, "end": 117, "line": 3, "column": 12, "endLine": 3, "endColumn": 36, "label": "" }, "callable": "test \"a long plan still adds up\"", "repeats": 1 } ] }, "rerun": "jadpo test plans.test.jadpo:3 --seed 1"}
Every location, a test's, a failure's at, a stack frame's and a
diagnostic's, has the one shape path, start, end, line, column,
endLine, endColumn, label. A stack frame is { location, callable, repeats }, a recursion counted once. A project with errors runs nothing:
data is { ran: false, root, fileCount, errors, warnings } and the errors
are the diagnostics. --failed with nothing to rerun gives { selection, gone, tests: [] }, where gone counts the tests that failed last time and
are no longer in the project. --watch --json writes one document per
line, its data with a watch object (event, changed, reached,
failing, files, fixed).
Markdown for agents: /docs/assertions.md.Built from Jadpo main at a707efb.