cljs.core/test
的行为与它的文档字符串描述不一致。
cljs.core/test
的定义是
(defn test
"test [v] finds fn at key :test in var metadata and calls it,
presuming failure will throw exception"
[v]
(let [f (.-cljs$lang$test v)]
(if f
(do (f) :ok)
:no-test)))
根据我的理解,它应该这样使用(示例从 ClojureDocs 上记录的相同函数的文档版本复制,https://docs.clojure.org/clojure.core/test#example-542692cac026201cdc326b8a )
(defn my-function
"this function adds two numbers"
{:test #(do
(assert (= (my-function 2 3) 5))
(assert (= (my-function 4 4) 8)))}
([x y] (+ x y)))
(test #'my-function) ;equal to (test (var my-function))
=> :ok
因此,cljs.core/test
通过在 :test
键下提供的测试来使函数能够自我描述其功能。
然而,在 CLJS 环境中重复上述内容会产生不同的结果
(defn my-function
"this function adds two numbers"
{:test #(do
(assert (= (my-function 2 3) 5))
(assert (= (my-function 4 4) 8)))}
([x y] (+ x y)))
(test #'my-function)
=> :no-test
有趣的是,鉴于我在 CLJS REPL 中评估了上述内容, metadata 确实是可用的,据我所知
(meta #'my-function)
=>
{:ns cljs.user,
:name my-function,
:file "<cljs repl>",
:end-column 18,
:source "my-function",
:column 1,
:line 1,
:end-line 1,
:arglists ([x y]),
:doc "this function adds two numbers",
:test #object[Function]}
通过用一个关键字替换这个相当模糊的函数,可以使情况更加清晰
(defn my-function
"this function adds two numbers"
{:test :just-a-keyword}
([x y] (+ x y)))
(meta #'my-function)
=>
{:ns cljs.user,
:name my-function,
:file "<cljs repl>",
:end-column 18,
:source "my-function",
:column 1,
:line 1,
:end-line 1,
:arglists ([x y]),
:doc "this function adds two numbers",
:test :just-a-keyword}
我曾在 Clojurians Slack 上与 @theller 和 @hiredman 讨论过这个问题,他们推测 cljs.core/test
已经被重新用于执行 deftest
的体,因为这两者似乎相匹配。观察
(require '[cljs.test :as test])
(test/deftest foo (test/is (= 1 2)))
=> #'cljs.user/foo
(test foo)
FAIL in () (<NO_SOURCE_FILE>:1:28)
expected: (= 1 2)
actual: (not (= 1 2))
:ok
deftest
的体被执行,并返回了关键字 :ok
(无论 is
的结果如何),从阅读 cljs.core/test
的定义中也可以看出。
如果 cljs.core/test
以这种方式被重新用于,那么还有两点也是真实的
A) 如果曾经打算让 cljs.core/test
启用测试 defn
的 :test
声明,那么现在不再是这样了。
B) cljs.core/test
的文档字符串有些误导。
文档字符串的第一部分,"test [v] finds fn at key :test in var metadata and calls it"
,在技术上可能是正确的,但它没有提到与 deftest
的任何联系,因此有些无帮助。
文档字符串的第二部分,", 假设失败将抛出异常"
,当用于 deftest
时肯定是不正确的——大多数 deftest
都会使用 cljs.test/is
宏,我认为这是公平的——它捕获异常并报告。我认为原始意图是抛出异常,以使 :ok
不返回,但在这个上下文中,这个结构会失败。
这个文档字符串似乎只是 Clojure 版本的副本,所以可能需要更新。或者,cljs.core/test
到目前为止可能是未使用的并且是冗余的?