Skip to content

Testing

Three layers of testing run today: vitest unit/integration tests, an architecture-checks pass that enforces structural rules, and a demo-runner that exercises end-to-end LLM interactions.

vitest

bash
# from projects/omega-lisp/
pnpm test          # vitest run
pnpm test:watch    # vitest in watch mode
pnpm test:ci       # CI variant

Tests live in projects/omega-lisp/test/ and projects/omega-lisp/packages/*/test/. The vitest config at vitest.config.ts controls inclusion/exclusion patterns and aliases for workspace cross-imports.

Common test patterns:

  • Reentry tests (test/oracle/reentry.spec.ts) — verify the co-recursive tower (Lisp → LLM → Lisp). The R6 test in particular proves nested LLM calls work.
  • Effect tests — drive an EffectBackend with synthesized op calls, assert the machine's response.
  • Module tests — compile a module, instantiate it, verify the exports and capabilities match the manifest.
  • Reader/parser tests — round-trip source → datum → source.

Architecture checks

bash
pnpm arch:checks

Runs scripts/architecture-checks.mjs, which enforces structural constraints — for example:

  • packages/core/ does not import from anywhere outside its own narrow facade.
  • The Matrix-membrane consumers don't reach into REPL or driver code.
  • Every package has a manifest and a provide matching its define-package exports.

The full check is part of pnpm arch:baseline, which is the canonical "is this package shippable" gate (package.json:59).

Demo runner

bash
pnpm demo                  # runs bin/manual-runner.ts demo 0 — the showcase
pnpm demo-instant          # runs demo/lisp/ch00-instant-showcase.lisp via the REPL
pnpm demo:proof            # runs scripts/demo-proof.mjs

The demo files under demo/lisp/ are also informal regression tests — they assume specific LLM behavior and exercise full-stack flows.

Testing user Lisp code

Two patterns:

1. Run code through the REPL CLI

bash
pnpm omega-fast -- --cmd "(my-fn 42)"
# exit code = 0 if no error; output = printed result

For more control, use --file to run a script:

bash
pnpm omega-fast -- --file my-test.lisp

2. Use OmegaRepl as a library

ts
import { OmegaRepl } from 'omega-lisp/repl';
import { describe, expect, test } from 'vitest';

describe('my-fn', () => {
  test('basic case', async () => {
    const repl = new OmegaRepl();
    await repl.eval('(load "lib/my-pkg.lisp")');
    const result = await repl.eval('(my-fn 42)');
    expect(result.value).toEqual({ tag: 'Num', n: 84 });
  });
});

This pattern is used in test/repl/*.spec.ts.

Testing with mock providers

For tests that exercise oracle calls without hitting real APIs:

ts
import { DriverRegistry } from '@open-matrix/inference';
import { MockDriver } from '@open-matrix/driver-mock';

const registry = new DriverRegistry();
registry.register('mock', new MockDriver({ /* canned responses */ }));

const omega = new OmegaRuntime({ registry, defaultDriver: 'mock' });

The mock driver is always registered when present. Its responses are programmable per-prompt.

See also

Source: projects/omega-lisp/package.json (scripts.test, arch:checks, arch:baseline), projects/omega-lisp/vitest.config.ts, projects/omega-lisp/scripts/architecture-checks.mjs.