Open Manual

<!-- nytrix-doc: {"audience":"user","featured":true,"group":"learn","order":50,"summary":"Write focused tests, run fixture suites, and verify that the intended compiler or browser path executed."} -->

Testing

A Nytrix check is an executable source file that asserts behavior and exits

non-zero on failure.

Tests are ordinary programs. That keeps examples, regressions, and integration

checks close to the language users run outside the test harness.

Minimal check

use std.core
use std.core.iter as it

def xs = [1, 2, 3, 4]
assert_eq(it.filter(xs, fn(v){ (v % 2) == 0 }), [2, 4], "even values")
assert_eq(it.reduce(xs, 0, fn(acc, v){ acc + v }), 10, "sum")

Commands

ny --color=never path/to/check.ny
ny fmt --trim --check path/to/file.ny
ny test --pattern name
ny test --with-stdlib module-or-path

.nshape checks may use flags_matrix when the same source must be compiled

through several native backends. Rows are separated by ; or escaped newlines,

and each row is appended to the normal flags for one focused harness run.

Embedded Ny generators

When a deterministic fixture needs repetitive Ny source, keep the generator in

the .nshape instead of adding a companion script or expanding hundreds of

near-identical lines:

source ny generate awk <<'AWK'
BEGIN {
  print "use std.core"
  for (i = 0; i < 100; i++)
    print "print(" i ")"
}
AWK

The opener and closing marker follow the existing source-block convention.

ny-test writes the block verbatim to a private temporary AWK program, runs

awk with empty input using separate arguments (never a shell command), and

uses standard output as the Ny source. A missing or malformed block, unavailable

awk, nonzero generator exit, or empty output is a fixture failure. Literal

source ny blocks remain supported and take precedence for compatibility.

Native optimizer stress

Native optimizer regressions use a small, deterministic source program and an

optimization-level matrix. Each row runs the NYIR VM and the selected native

backend through --native-result-oracle; a result mismatch is a failure. Keep

the fixture target-specific and focused on one control-flow or lowering shape,

then cover broader input variation through the existing shapes/ fuzz corpus.

This gives every fixed optimizer bug a reproducible regression while keeping

generated stress separate from correctness baselines.

LD_LIBRARY_PATH=build/vendor/lib/host \
  ./build/release/ny-test --jobs 8 --failures-only \
  etc/tests/native/oracle/*optimizer*levels*x86-64.nshape

Check classes

ClassScope
ValuePure function, parser, encoder, or transform returns an exact value.
BoundaryFile, process, socket, FFI call, or native handle crosses runtime boundaries.
RegressionA fixed bug has a small reproducer.
IntegrationMultiple modules cooperate.
VisualUI, image, font, renderer, or scene behavior changed.
PerformanceTiming, allocation, throughput, or generated-code behavior changed.

Repository suites

The repository keeps test inputs with the subsystem that owns their behavior:

etc/tests/
  runtime/   ordinary Nytrix behavior, grouped by language/runtime concern
  errors/    expected parser, type, ownership, and safety diagnostics
  native/    NYIR, backend, object, linker, oracle, and sanitizer checks
  interop/   C headers, FFI fixtures, and Nytrix interop entry programs
  bench/     checksum-producing compile and throughput workloads
  shapes/    fuzz generators, probes, stress inputs, and compiler regressions

Run a .ny file directly. Run a .nshape specification through ny-test;

it is harness metadata, not source code for ny itself.

ny-test executes the repository tree as one deterministic run while reporting

Runtime, Native, and Interop ownership separately.

Benchmark .nshape fixtures use their checksum= output as the cross-backend

equivalence contract. For protected performance cases, fixture metadata may add

max_native_c_ratio or max_native_llvm_ratio; the canonical benchmark runner

fails the row when the measured median exceeds that fixture-specific ratio.

Use --bench-correctness for the one-run semantic smoke path and at least five

measured runs for noise-aware performance gating.

./make test --with-stdlib --failures-only
LD_LIBRARY_PATH=build/vendor/lib/host \
  ./build/release/ny-test --jobs 8 etc/tests/native --failures-only
./build/release/ny-fuzz compiler known-bugs --json /tmp/ny-known-bugs.json

Assertions

use std.core

def condition = true
def actual = [1, 2]
def expected = [1, 2]

assert(condition, "behavior name")
assert_eq(actual, expected, "behavior name")

Assertion messages name behavior, not implementation details. Exact-value

assertions define deterministic behavior. Timing assertions are performance

checks.

IO boundaries

BoundaryDeterministic setup
FilesTemporary path, exact readback, cleanup.
ProcessesBounded command, explicit stdin/stdout, timeout.
SocketsLocal server, readiness check, timeout.
HTTPLocal fixture server or documented local service requirement.
TLSResponse transport/error metadata included in assertion.
TerminalColor disabled unless color is the behavior under test.

Code fences

Every code fence declares what it contains:

FenceRule
nyComplete Nytrix source that must compile as an extracted doc fence.
bashShell command.
jsonManifest or data payload.
textGrammar, output, directory tree, non-source transcript, or contextual source fragment.

Silent success is valid for runnable examples. Assertion failure, panic, nonzero

exit status, or diagnostic output carries the failure signal.

Completion

A change is complete when the focused check passes, relevant formatting/audit

commands pass, and the required build or test target passes.

For compiler, runtime, stdlib, or docs-generator changes, run

./make test --with-stdlib. For documentation-only changes, run ./make docs

and any focused checks for changed examples.