clojure.test/are substitutes via clojure.template

are let-bound its template vars, so a var inside quote never substituted:
(are [x] (special-symbol? 'x) if def) tested the literal symbol x twice.
Rebuild are on clojure.template/do-template (postwalk substitution), the
same architecture as upstream, with the same arg-count check.

This un-aborts every suite namespace whose are rows need substitution:
cts baseline moves 5302->5614 pass, 236->192 errors, 88->84 baselined
namespaces. The newly-reachable assertions also surface real divergences
now baselined and filed (edn reader strictness, Boolean ctor).
This commit is contained in:
Yogthos 2026-07-02 05:57:57 -04:00
parent 53a8aac2d0
commit 86e36e8bee
4 changed files with 61 additions and 21 deletions

View file

@ -11,7 +11,8 @@
; is a drop-in superset.
(ns clojure.test
(:require [clojure.string :as str]))
(:require [clojure.string :as str]
[clojure.template :as temp]))
;; --- state -----------------------------------------------------------------
@ -216,13 +217,16 @@
:fn ~name})
(var ~name)))
(defmacro are [argv expr & data]
(let [n (count argv)
rows (partition n data)]
`(do ~@(map (fn [row]
`(let [~@(interleave argv row)]
(clojure.test/is ~expr)))
rows))))
;; Template substitution (not let-binding), so argv symbols substitute inside
;; quote and nested forms: (are [x] (special-symbol? 'x) if def) tests 'if.
(defmacro are [argv expr & args]
(if (or (and (empty? argv) (empty? args))
(and (pos? (count argv))
(pos? (count args))
(zero? (mod (count args) (count argv)))))
`(clojure.template/do-template ~argv (clojure.test/is ~expr) ~@args)
(throw (IllegalArgumentException.
"The number of args doesn't match are's argv or neither are empty"))))
;; --- fixtures + run --------------------------------------------------------