Output, debugging, and tests
Console, Debug, and Testing serve different purposes. Keeping those
purposes separate makes application output, diagnostics, and tests easier to
maintain.
User-facing output with Console
Section titled “User-facing output with Console”Console.println(value : String) prints one string followed by a host-defined
line terminator:
func main() -> Unit do Console.println("Build complete");endConvert domain values to appropriate user-facing text before printing. Debug representation is not a stable serialization or product-copy format.
Structural inspection with Debug
Section titled “Structural inspection with Debug”Debug.trace(value) resolves IDebug for T, renders a bounded structural
representation, prints it, and returns Unit:
datatype Event Event{name: String, code: Int}end
func main() -> Unit do Debug.trace(Event::Event{name: "ready", code: 200});endDebug.to_debug_string(value) returns the rendered string instead of printing
it. Debug.render(repr) renders an already-created Debug.Repr.
The renderer quotes strings and characters, preserves structural field and constructor information, limits expansion depth, and may omit collection elements after a finite bound. It is designed for diagnostics rather than round-tripping.
The IDebug provider, lazy Debug.Repr model, and its relationship to
structural equality, ordering, and hashing are explained in
Structural capabilities.
Test declarations
Section titled “Test declarations”A test is a named, parameterless module declaration checked as a Unit body:
func add(left : Int, right : Int) -> Int do left + rightend
test "adds two integers" do Testing.assert_equal(add(20, 22), 42)!;endRun all tests declared by one package with:
noodle test .Tests may access private declarations in their own module. They are excluded from production signatures and ordinary production module artifacts.
Assertions
Section titled “Assertions”The public assertion helpers are:
Testing.assert(condition)!;Testing.assert_equal(actual, expected)!;Testing.fail(message)!.
assert_equal resolves both equality and debug providers for the concrete
type. On failure it records rendered actual and expected values plus compiler-
autofilled source locations for both argument expressions.
A test infers the error types propagated directly from its body, so assertions
and application Result values can both use postfix ! without an explicit
test-level throws clause. Nested functions inside a test still need their own
ordinary error contract.
Test order and isolation
Section titled “Test order and isolation”The runner orders modules by derived module name and preserves source order within each module. Tests run serially. One failure does not prevent later tests from running.
Each test is guarded by a timeout in an isolated, terminable execution unit.
Ordinary tests default to 200 milliseconds; @expensive tests default to
15,000 milliseconds. The CLI accepts --timeout, --expensive-timeout, and
--compile-timeout overrides, all as positive millisecond values.
noodle test --quick still checks and compiles all tests, skips execution of
tests marked @expensive, and reports the skipped count in its summary.
An async test uses async test and may await tasks. The same pass/fail and
timeout model applies; see Asynchronous code.
This completes the main documentation path. Return to Language basics or revisit Advanced topics as your program grows.