Files
rose-ash/sx/sx/language/test/runners/index.sx
giles 4f02f82f4e HS parser: fix number+comparison keyword collision, eval-hs uses hs-compile
Parser: skip unit suffix when next ident is a comparison keyword
(starts, ends, contains, matches, is, does, in, precedes, follows).
Fixes "123 starts with '12'" returning "123starts" instead of true.

eval-hs: use hs-compile directly instead of hs-to-sx-from-source with
"return " prefix, which was causing the parser to consume the comparison
as a string suffix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 11:29:01 +00:00

110 lines
7.2 KiB
Plaintext

;; ---------------------------------------------------------------------------
;; Runners page
;; ---------------------------------------------------------------------------
(defcomp ()
(~docs/page :title "Test Runners"
(div (~tw :tokens "space-y-8")
(div (~tw :tokens "space-y-4")
(p (~tw :tokens "text-lg text-stone-600")
"Three runners execute the same test specs on different hosts. Each injects the five platform functions and any per-spec extensions, then evaluates the SX source directly.")
(p (~tw :tokens "text-stone-600")
"All runners produce "
(a :href "https://testanything.org/" (~tw :tokens "text-violet-700 underline") "TAP")
" output and accept module names as arguments."))
;; Node.js runner
(div (~tw :tokens "space-y-3")
(h2 (~tw :tokens "text-2xl font-semibold text-stone-800") "Node.js: run.js")
(div (~tw :tokens "rounded-lg border border-stone-200 bg-white p-5 space-y-3")
(h3 (~tw :tokens "text-sm font-medium text-stone-500 uppercase tracking-wide") "Usage")
(~docs/code :src
(highlight "# Run all specs\nnode shared/sx/tests/run.js\n\n# Run specific specs\nnode shared/sx/tests/run.js eval parser\n\n# Legacy mode (monolithic test.sx)\nnode shared/sx/tests/run.js --legacy" "bash")))
(p (~tw :tokens "text-stone-600 text-sm")
"Uses "
(code (~tw :tokens "text-violet-700 text-sm") "sx-browser.js")
" as the evaluator. Router tests use bootstrapped functions from "
(code (~tw :tokens "text-violet-700 text-sm") "Sx.splitPathSegments")
" etc. Render tests use "
(code (~tw :tokens "text-violet-700 text-sm") "Sx.renderToHtml")
"."))
;; Python runner
(div (~tw :tokens "space-y-3")
(h2 (~tw :tokens "text-2xl font-semibold text-stone-800") "Python: run.py")
(div (~tw :tokens "rounded-lg border border-stone-200 bg-white p-5 space-y-3")
(h3 (~tw :tokens "text-sm font-medium text-stone-500 uppercase tracking-wide") "Usage")
(~docs/code :src
(highlight "# Run all specs\npython shared/sx/tests/run.py\n\n# Run specific specs\npython shared/sx/tests/run.py eval parser\n\n# Legacy mode (monolithic test.sx)\npython shared/sx/tests/run.py --legacy" "bash")))
(p (~tw :tokens "text-stone-600 text-sm")
"Uses the hand-written Python evaluator ("
(code (~tw :tokens "text-violet-700 text-sm") "evaluator.py")
"). Router tests import bootstrapped functions from "
(code (~tw :tokens "text-violet-700 text-sm") "sx_ref.py")
" because the hand-written evaluator's "
(code (~tw :tokens "text-violet-700 text-sm") "set!")
" doesn't propagate across lambda closure copies."))
;; Browser runner
(div (~tw :tokens "space-y-3")
(h2 (~tw :tokens "text-2xl font-semibold text-stone-800") "Browser: sx-test-runner.js")
(p (~tw :tokens "text-stone-600")
"Runs in the browser on each test page. The spec source is embedded in a hidden textarea; the runner parses and evaluates it using the same "
(code (~tw :tokens "text-violet-700 text-sm") "sx-browser.js")
" that renders the page itself.")
(p (~tw :tokens "text-stone-600")
"This is the strongest proof of cross-host parity — the browser evaluator that users depend on is the same one running the tests."))
;; Platform functions table
(div (~tw :tokens "space-y-3")
(h2 (~tw :tokens "text-2xl font-semibold text-stone-800") "Platform functions")
(div (~tw :tokens "overflow-x-auto rounded border border-stone-200")
(table (~tw :tokens "w-full text-left text-sm")
(thead (tr (~tw :tokens "border-b border-stone-200 bg-stone-100")
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Function")
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Scope")
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Purpose")))
(tbody
(tr (~tw :tokens "border-b border-stone-100")
(td (~tw :tokens "px-3 py-2 font-mono text-sm text-violet-700") "try-call")
(td (~tw :tokens "px-3 py-2") "All specs")
(td (~tw :tokens "px-3 py-2 text-stone-700") "Call a thunk, catch errors, return result dict"))
(tr (~tw :tokens "border-b border-stone-100")
(td (~tw :tokens "px-3 py-2 font-mono text-sm text-violet-700") "report-pass")
(td (~tw :tokens "px-3 py-2") "All specs")
(td (~tw :tokens "px-3 py-2 text-stone-700") "Report a passing test"))
(tr (~tw :tokens "border-b border-stone-100")
(td (~tw :tokens "px-3 py-2 font-mono text-sm text-violet-700") "report-fail")
(td (~tw :tokens "px-3 py-2") "All specs")
(td (~tw :tokens "px-3 py-2 text-stone-700") "Report a failing test with error message"))
(tr (~tw :tokens "border-b border-stone-100")
(td (~tw :tokens "px-3 py-2 font-mono text-sm text-violet-700") "push-suite")
(td (~tw :tokens "px-3 py-2") "All specs")
(td (~tw :tokens "px-3 py-2 text-stone-700") "Push suite name onto context stack"))
(tr (~tw :tokens "border-b border-stone-100")
(td (~tw :tokens "px-3 py-2 font-mono text-sm text-violet-700") "pop-suite")
(td (~tw :tokens "px-3 py-2") "All specs")
(td (~tw :tokens "px-3 py-2 text-stone-700") "Pop suite name from context stack"))
(tr (~tw :tokens "border-b border-stone-100")
(td (~tw :tokens "px-3 py-2 font-mono text-sm text-violet-700") "sx-parse")
(td (~tw :tokens "px-3 py-2") "Parser")
(td (~tw :tokens "px-3 py-2 text-stone-700") "Parse SX source to AST"))
(tr (~tw :tokens "border-b border-stone-100")
(td (~tw :tokens "px-3 py-2 font-mono text-sm text-violet-700") "sx-serialize")
(td (~tw :tokens "px-3 py-2") "Parser")
(td (~tw :tokens "px-3 py-2 text-stone-700") "Serialize AST back to SX source text"))
(tr (~tw :tokens "border-b border-stone-100")
(td (~tw :tokens "px-3 py-2 font-mono text-sm text-violet-700") "render-html")
(td (~tw :tokens "px-3 py-2") "Renderer")
(td (~tw :tokens "px-3 py-2 text-stone-700") "Parse SX source and render to HTML string"))))))
;; Adding a new host
(div (~tw :tokens "rounded-lg border border-blue-200 bg-blue-50 p-5 space-y-3")
(h2 (~tw :tokens "text-lg font-semibold text-blue-900") "Adding a new host")
(ol (~tw :tokens "list-decimal list-inside text-blue-800 space-y-2 text-sm")
(li "Implement the 5 platform functions in your target language")
(li "Load " (code (~tw :tokens "text-sm") "test-framework.sx") " — it defines deftest/defsuite macros")
(li "Load the spec file(s) — the evaluator runs the tests automatically")
(li "Add per-spec platform functions if testing parser or renderer")
(li "Compare TAP output across hosts — divergences reveal platform-specific semantics"))))))