This list captures behavior the squint (and cherry) cljs.test built-ins
don't yet match against the canonical clojure.test / cljs.test. The
ordering is rough priority — high-impact correctness gaps first, then
extensibility gaps, then polish.
~~set-each-fixtures! / set-once-fixtures! write into the single global
env. Real clojure.test keys fixtures by namespace ((alter-meta! ns ...)).
Today, two test namespaces each calling (use-fixtures :each ...) will
clobber each other; whichever loaded last wins for every test.~~
Fixed: :each-fixtures and :once-fixtures are now {ns-str → vec}
maps; core-deftest stashes :ns in the test fn's meta; test-var
and run-tests look fixtures up by that ns. The 1-arg legacy setters
target a nil-keyed bucket for back-compat. Regression tests in both
the squint smoke suite and cherry's cross_platform_test.
~~(run-tests) auto-inits the env only when *current-env* is nil. A
second (run-tests) in the same module reuses (and inflates) the
existing counters. Tests that themselves invoke run-tests (squint and
cherry's own runtime tests do this) emit summaries showing cumulative
counts, not per-run counts.~~
Fixed: run-tests saves the caller's :report-counters, runs against
fresh ones, restores on return. The returned summary map reflects only
that run. Inner run-tests calls now show their own per-call summary
instead of polluted cumulative totals. Regression tests in both repos.
is reportingThe shared macro (:name '~name) would expand to cljs.core.symbol(...)
under squint, which doesn't exist at runtime. We worked around it by
storing :name as a string (and assert-expr uses (pr-str form)).
Result: (:name (meta test-fn)) is a string, not a symbol — diverges
from clojure.test's expectations and breaks code that calls
namespace/name on it.
Fix sketch: fix squint's quote emission to route through
squint_core.symbol (already a real fn) instead of the literal
cljs.core.symbol. Then revert macros to symbol form for parity with
cherry/cljs.test.
assert-expr is hardcodedReal clojure.test/assert-expr is a multimethod keyed on the head of
the form inside (is ...). Users add new assertions by defmethod-ing
it. Ours is a case over =, thrown?, thrown-with-msg?. No
extension point.
Fix sketch: make assert-expr a multimethod (or a registry of
{op-sym (fn [msg form] ...)}) that the macro consults. Squint can ship
the existing four cases as default methods.
report is hardcoded too ✅ DONE~~clojure.test/report is a multimethod keyed on :type; users add
methods to extend reporting (e.g. cljs-test-display). Ours is a single
case defn.~~
Fixed: report is now a defmulti dispatching on
[*current-reporter* (:type m)], matching cljs.test. The built-in
reporter lives under :cljs.test/default; unknown combinations fall
through to a no-op :default method. test-var now also emits
:begin-test-var / :end-test-var so reporters can bracket per-var
output. Smoke test report-is-multimethod-test covers user-defined
extensions.
test-var is a plain fnclojure.test/test-var is a multimethod (:default impl is what
everyone uses, but it's overridable). Same idea as report.
:begin-test-ns / :end-test-ns are never emitted ✅ DONE~~We support the report types in report's case, but run-tests never
fires them. Real clojure.test brackets each ns it processes with these
events; reporters use them to group output.~~
Fixed: run-vars-with-once-fixtures now brackets each ns's tests with
:begin-test-ns / :end-test-ns reports, so (t/run-tests 'my.ns)
prints Testing my.ns like cljs.test. Anonymous (nil-ns) groups are
skipped. Smoke tests assert the lines appear.
(t/async done body) form ✅ DONE~~Real cljs.test async tests use (async done (do ... (done))). We use
^:async on the deftest plus a Promise-returning body. Functionally
equivalent but different surface — code copied from a CLJS project
won't run.~~
Added: core-async macro expands (async done body) to
(js/Promise. (fn [done] body)). test-var already awaits any
Promise-returning test fn, so no additional plumbing was needed —
the ^:async form keeps working too. Regression tests in both repos.
clojure.test/run-tests walks ns-publics and filters by
(:test (meta var)). We use a separate test-registry because squint
has no var metadata at runtime. That works for tests defined via our
deftest, but a user who manually attaches :test true to a defn
won't be picked up.
Note: unclear this is fixable without a var registry — probably accept the divergence and document.
successful? reads global counters~~ — non-issueOn re-read: successful? takes a counters map and reads :fail/:error
from it. No global state involved. Removed.
run-tests calls produce double summary output ✅ DONE~~Two of cherry's cross_platform_test cases call run-tests inside test
bodies (testing the runtime itself). Each emits its own :summary line,
on top of the outer test run's summary.~~
Side-effect of #2: each inner run-tests now reports its own per-call
summary with accurate counts (instead of cumulative pollution). Still
multiple summary lines, but the lines are correct and informative —
not noise. Closing.
:report-counters :summary increments needlesslyreport calls (inc-report-counter! :type) unconditionally, including
for :type :summary. Adds a meaningless counter to the env map.
*test-out* redirectionOutput goes hard-wired to js/console.log/js/console.error. Real
cljs.test lets users rebind via *report-out* or per-method.
Both implement the same surface but are separate .cljs files. Easy to
fix one and forget the other. Could share via a .cljc if we factor
out the few JS-vs-CLJS differences.
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |