2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!请参阅 关于 页面,以了解更多关于此如何运作的信息。

0
ClojureScript

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 中评估了上述代码,据我所知,元数据确实是可用的。

(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 的定义中得出。

如果真的是这样的话,那么还有两个真实的情况:

A) 如果原本的意图是让 cljs.core/test 启用对 defn:test 断言进行测试,那么这不再成立。
B) cljs.core/test 的文档字符串有点误导。

文档字符串的开头部分,"test [v] finds fn at key :test in var metadata and calls it" 可能是技术上正确的,但没有提到与 deftest 的关联,因此不是很有用。

文档字符串的第二部分,", presuming failure will throw exception",在用于 deftest 时显然是不正确的——我猜想大多数 deftest 都使用了 cljs.test/is 宏,它会捕获异常并代替报告。我认为原始的意图是抛出异常,这样就不会返回 :ok,但在这种上下文中,这个结构失败了。

文档字符串似乎是 Clojure 版本的复制品,所以可能需要更新。或者,cljs.core/test 可能在这个阶段既未使用又过时了?

1 个回答

0
by
...