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:
parent
53a8aac2d0
commit
86e36e8bee
4 changed files with 61 additions and 21 deletions
|
|
@ -196,6 +196,42 @@ cases; clojure-test-suite `core_test/parse_uuid.cljc`,
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### clojure.template/apply-template, clojure.test/are — since 1.1
|
||||||
|
|
||||||
|
```
|
||||||
|
(apply-template argv expr values)
|
||||||
|
(are argv expr & args)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Semantics**
|
||||||
|
|
||||||
|
- S1. `apply-template` MUST replace every occurrence of each `argv` symbol
|
||||||
|
in `expr` with its corresponding value by structural walk (postwalk symbol
|
||||||
|
substitution), not by lexical binding. Occurrences inside `quote` and at
|
||||||
|
any nesting depth substitute: `(apply-template '[x] '(f 'x) '[if])` ⇒
|
||||||
|
`(f 'if)`.
|
||||||
|
- S2. `do-template` MUST partition `args` by `(count argv)` and expand to a
|
||||||
|
`do` of one substituted `expr` per group.
|
||||||
|
- S3. `clojure.test/are` MUST expand through `do-template` with `expr`
|
||||||
|
wrapped in `is`. Consequently `(are [x] (special-symbol? 'x) if def)`
|
||||||
|
asserts `(special-symbol? 'if)` and `(special-symbol? 'def)` — a
|
||||||
|
let-binding implementation is non-conforming (the quoted symbol would not
|
||||||
|
substitute).
|
||||||
|
|
||||||
|
**Errors**
|
||||||
|
|
||||||
|
- X1. `are` MUST throw at macroexpansion when `(count args)` is not a
|
||||||
|
positive multiple of a non-empty `(count argv)` (empty/empty is allowed).
|
||||||
|
- X2. `apply-template` MUST throw when `argv` is not a vector of symbols.
|
||||||
|
|
||||||
|
**Conformance**
|
||||||
|
|
||||||
|
S1–S3 → `test/chez/clojure-test.clj` (are with quoted template var);
|
||||||
|
clojure-test-suite `core_test/special_symbol_qmark.cljc` and every
|
||||||
|
`are`-based suite namespace.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Authoring notes
|
## Authoring notes
|
||||||
|
|
||||||
- Source examples from the ClojureDocs export (`clojuredocs-export.edn`,
|
- Source examples from the ClojureDocs export (`clojuredocs-export.edn`,
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@
|
||||||
; is a drop-in superset.
|
; is a drop-in superset.
|
||||||
|
|
||||||
(ns clojure.test
|
(ns clojure.test
|
||||||
(:require [clojure.string :as str]))
|
(:require [clojure.string :as str]
|
||||||
|
[clojure.template :as temp]))
|
||||||
|
|
||||||
;; --- state -----------------------------------------------------------------
|
;; --- state -----------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -216,13 +217,16 @@
|
||||||
:fn ~name})
|
:fn ~name})
|
||||||
(var ~name)))
|
(var ~name)))
|
||||||
|
|
||||||
(defmacro are [argv expr & data]
|
;; Template substitution (not let-binding), so argv symbols substitute inside
|
||||||
(let [n (count argv)
|
;; quote and nested forms: (are [x] (special-symbol? 'x) if def) tests 'if.
|
||||||
rows (partition n data)]
|
(defmacro are [argv expr & args]
|
||||||
`(do ~@(map (fn [row]
|
(if (or (and (empty? argv) (empty? args))
|
||||||
`(let [~@(interleave argv row)]
|
(and (pos? (count argv))
|
||||||
(clojure.test/is ~expr)))
|
(pos? (count args))
|
||||||
rows))))
|
(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 --------------------------------------------------------
|
;; --- fixtures + run --------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,10 @@
|
||||||
(are [x y] (= x y)
|
(are [x y] (= x y)
|
||||||
2 (+ 1 1)
|
2 (+ 1 1)
|
||||||
6 (* 2 3))
|
6 (* 2 3))
|
||||||
|
;; template vars substitute inside quote (are is clojure.template, not let)
|
||||||
|
(are [x] (special-symbol? 'x)
|
||||||
|
if
|
||||||
|
def)
|
||||||
(is (thrown? clojure.lang.ExceptionInfo (throw (ex-info "x" {}))))
|
(is (thrown? clojure.lang.ExceptionInfo (throw (ex-info "x" {}))))
|
||||||
(is (thrown-with-msg? Exception #"bad" (throw (ex-info "bad" {}))))
|
(is (thrown-with-msg? Exception #"bad" (throw (ex-info "bad" {}))))
|
||||||
(is (near? 1.0 1.005))
|
(is (near? 1.0 1.005))
|
||||||
|
|
@ -52,10 +56,10 @@
|
||||||
(t/do-report {:type ::trial})
|
(t/do-report {:type ::trial})
|
||||||
(t/do-report {:type ::trial})
|
(t/do-report {:type ::trial})
|
||||||
|
|
||||||
;; 8 pass (= + vector? + 2 are rows + thrown? + thrown-with-msg? + near? + p/thrown?),
|
;; 10 pass (= + vector? + 4 are rows + thrown? + thrown-with-msg? + near? + p/thrown?),
|
||||||
;; 2 fail (= 1 2, near? 1.0 5.0), 0 error, 2 fixture runs, 2 custom reports
|
;; 2 fail (= 1 2, near? 1.0 5.0), 0 error, 2 fixture runs, 2 custom reports
|
||||||
(let [ok (and (= (t/n-pass) 8) (= (t/n-fail) 2) (= (t/n-error) 0)
|
(let [ok (and (= (t/n-pass) 10) (= (t/n-fail) 2) (= (t/n-error) 0)
|
||||||
(= 2 (:test r1)) (= 8 (:pass r1)) (= 2 (:fail r1))
|
(= 2 (:test r1)) (= 10 (:pass r1)) (= 2 (:fail r1))
|
||||||
(= 0 (:test r2)) (= 0 (:pass r2))
|
(= 0 (:test r2)) (= 0 (:pass r2))
|
||||||
(= @setups 2) (= @trials 2))]
|
(= @setups 2) (= @trials 2))]
|
||||||
(println (if ok
|
(println (if ok
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ clojure.core-test.ancestors 9 0
|
||||||
clojure.core-test.atom 14 0
|
clojure.core-test.atom 14 0
|
||||||
clojure.core-test.bigint 6 0
|
clojure.core-test.bigint 6 0
|
||||||
clojure.core-test.bit-set 1 0
|
clojure.core-test.bit-set 1 0
|
||||||
clojure.core-test.boolean-qmark 0 1
|
clojure.core-test.boolean-qmark 0 3
|
||||||
clojure.core-test.byte 7 5
|
clojure.core-test.byte 7 5
|
||||||
clojure.core-test.char 1 0
|
clojure.core-test.char 1 0
|
||||||
clojure.core-test.compare 1 0
|
clojure.core-test.compare 1 0
|
||||||
|
|
@ -26,8 +26,6 @@ clojure.core-test.eval 0 3
|
||||||
clojure.core-test.even-qmark 1 0
|
clojure.core-test.even-qmark 1 0
|
||||||
clojure.core-test.float 4 4
|
clojure.core-test.float 4 4
|
||||||
clojure.core-test.get 0 1
|
clojure.core-test.get 0 1
|
||||||
clojure.core-test.gt 0 2
|
|
||||||
clojure.core-test.gt-eq 0 2
|
|
||||||
clojure.core-test.ifn-qmark 2 0
|
clojure.core-test.ifn-qmark 2 0
|
||||||
clojure.core-test.inc 1 0
|
clojure.core-test.inc 1 0
|
||||||
clojure.core-test.int 4 5
|
clojure.core-test.int 4 5
|
||||||
|
|
@ -36,8 +34,6 @@ clojure.core-test.intern 2 0
|
||||||
clojure.core-test.keys 0 4
|
clojure.core-test.keys 0 4
|
||||||
clojure.core-test.lazy-seq 3 0
|
clojure.core-test.lazy-seq 3 0
|
||||||
clojure.core-test.long 2 5
|
clojure.core-test.long 2 5
|
||||||
clojure.core-test.lt 0 2
|
|
||||||
clojure.core-test.lt-eq 0 2
|
|
||||||
clojure.core-test.max 3 1
|
clojure.core-test.max 3 1
|
||||||
clojure.core-test.min 3 1
|
clojure.core-test.min 3 1
|
||||||
clojure.core-test.minus 2 0
|
clojure.core-test.minus 2 0
|
||||||
|
|
@ -56,23 +52,23 @@ clojure.core-test.plus 11 0
|
||||||
clojure.core-test.plus-squote 11 0
|
clojure.core-test.plus-squote 11 0
|
||||||
clojure.core-test.pop 0 1
|
clojure.core-test.pop 0 1
|
||||||
clojure.core-test.pos-int-qmark 1 0
|
clojure.core-test.pos-int-qmark 1 0
|
||||||
clojure.core-test.quot 12 31
|
clojure.core-test.quot 12 23
|
||||||
clojure.core-test.rand-nth 0 1
|
clojure.core-test.rand-nth 0 1
|
||||||
clojure.core-test.rational-qmark 3 0
|
clojure.core-test.rational-qmark 3 0
|
||||||
clojure.core-test.rationalize 10 0
|
clojure.core-test.rationalize 10 0
|
||||||
clojure.core-test.realized-qmark 3 0
|
clojure.core-test.realized-qmark 3 0
|
||||||
clojure.core-test.reduce 0 1
|
clojure.core-test.reduce 0 1
|
||||||
clojure.core-test.rem 12 30
|
clojure.core-test.rem 12 22
|
||||||
clojure.core-test.remove-watch 0 1
|
clojure.core-test.remove-watch 0 1
|
||||||
clojure.core-test.run-bang 1 0
|
clojure.core-test.run-bang 1 0
|
||||||
clojure.core-test.select-keys 2 0
|
clojure.core-test.select-keys 2 0
|
||||||
clojure.core-test.seqable-qmark 1 0
|
clojure.core-test.seqable-qmark 1 0
|
||||||
clojure.core-test.short 7 5
|
clojure.core-test.short 7 5
|
||||||
clojure.core-test.shuffle 1 0
|
clojure.core-test.shuffle 1 0
|
||||||
clojure.core-test.slash 2 48
|
clojure.core-test.slash 2 22
|
||||||
clojure.core-test.some-fn 3 0
|
clojure.core-test.some-fn 3 0
|
||||||
clojure.core-test.sort-by 2 0
|
clojure.core-test.sort-by 2 0
|
||||||
clojure.core-test.special-symbol-qmark 20 0
|
clojure.core-test.special-symbol-qmark 4 0
|
||||||
clojure.core-test.star 22 0
|
clojure.core-test.star 22 0
|
||||||
clojure.core-test.star-squote 19 0
|
clojure.core-test.star-squote 19 0
|
||||||
clojure.core-test.transient 23 0
|
clojure.core-test.transient 23 0
|
||||||
|
|
@ -82,7 +78,7 @@ clojure.core-test.vals 0 3
|
||||||
clojure.core-test.vec 1 0
|
clojure.core-test.vec 1 0
|
||||||
clojure.core-test.when-let 1 0
|
clojure.core-test.when-let 1 0
|
||||||
clojure.core-test.with-precision 17 0
|
clojure.core-test.with-precision 17 0
|
||||||
clojure.edn-test.read-string 0 1
|
clojure.edn-test.read-string 46 5
|
||||||
clojure.string-test.capitalize 0 4
|
clojure.string-test.capitalize 0 4
|
||||||
clojure.string-test.ends-with-qmark 1 4
|
clojure.string-test.ends-with-qmark 1 4
|
||||||
clojure.string-test.escape 1 0
|
clojure.string-test.escape 1 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue