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

欢迎!请查阅 关于 页面以了解更多关于此处工作的信息。

0
Spec

当尝试手动将 clojure.test 和 spec 连接到 fdef'ed 函数时,我发现 spec.test/check 返回一个包含 (link: :failure false) 的映射,对于失败的测试。我(几乎)确信它应该返回 true,因为 spec.test/abbrev-result 以 spec.test/check 的返回值为参数,并测试 :failure 的值。我无法创建一个 spec.test/check 返回 (link: :failure true) 给失败的测试的情况。顺便说一下,对于通过测试,返回不包含 :failure 键的映射。

以下是在 REPL 中的简单重现案例

(defn foo-fn (link: x) "bar")

(s/fdef foo-fn

    :args (s/cat :x any?)
    :ret string?)

(stest/check `foo-fn) ;; => 无错误,正常的小映射打印,没有 :failure 条目

(defn foo-fn (link: x) 1)

(stest/check `foo-fn) ;; => 完整错误映射,:failure 等于 false。:failure 如下所示

(-> (stest/check `foo-fn) first :failure) ;; => false

9 个答案

0

评论者:gfredericks

这虽然不算是错误,但确实令人困惑。

{{stest/check}} 在传递(至少部分)来自 {{clojure.test.check/quickcheck}} 的返回值,该值返回用于评估真实性以确定通过或失败属性值。

test.check 的下一个版本应该有更实用、更不令人困惑的方式来提取测试信息,但我不确定在 {{stest/check}} 中这会是什么样子。

0

评论人:djebbz

我还是不明白你为什么不把它视为一个错误。`stest/check` 的文档字符串说 “:failure 可选测试失败”。我预计只有当测试失败时才会出现 `:failure` 键(因此文字是“可选”),并包含一些有价值的信息。

我使用 stest/abbrev-result 来显示 stest/check 的输出,它期望 :failure 为真值以显示所有有价值的失败信息。如果 stest/check 返回 false,这将是一个我不认为是错误的差异。`stest/abbrev-result` 的文档字符串明确说明它接收检查的结果作为参数,因此我没有试图把方钉塞进圆孔中。

感谢您这么快回答我,并感谢您抽出时间。

0
_评论人:grzm_

{{:failure}} 的 {{false}} 值确实令人困惑。如 [~djebbz] 所指出,{{stest/abbrev-result}} 在 {{{{{:failure false}}}}} 中非常令人困惑,因为它没有提供失败通常提供的一些额外信息。

{code:title=https://github.com/clojure/spec.alpha/blob/2824ad49df8deadcb4b75acdf624e732a85b4ac7/src/main/clojure/clojure/spec/test/alpha.clj#L438-L446}
(defn abbrev-result
  "给定检查结果,返回适合摘要使用的简略版本。"

  [x]
  (if (:failure x)
    (-> (dissoc x ::stc/ret)
        (update :spec s/describe)
        (update :failure unwrap-failure))
    (dissoc x :spec ::stc/ret)))


以下是一个示例,说明它可能有多大的误导性


(require '[clojure.spec.alpha :as s]
         '[clojure.spec.test.alpha :as stest])

(alias 'stc 'clojure.spec.test.check)

(defn adder [a b]
  (+ a b))

(s/fdef adder
        :args (s/cat :a int? :b int?)
        :ret string?)

(-> (stest/check `adder) first stest/abbrev-result)
;; => {:sym ex.check-test/adder, :failure false}

;; 写一个 `abbrev-result` 的替代版本,检查 `true`


(defn- failure-type [x] (::s/failure (ex-data x)))
(defn- unwrap-failure [x] (if (failure-type x) (ex-data x) x))

(defn- abbrev-result [x]
  (let [failure (:failure x)]
    (if-not (or (true? failure)
                (nil? failure))
      (-> (dissoc x ::stc/ret)
          (update :spec s/describe)
          (update :failure unwrap-failure))
      (dissoc x :spec ::stc/ret))))

(-> (stest/check `adder) first abbrev-result)
;; => {:spec (fspec :args (cat :a int? :b int?) :ret string? :fn nil),
;;     :sym ex.check-test/adder,
;;     :failure false}


再次注意,任何真实的 {{:failure}} 值都将提供额外的细节,而假的 {{:failure}} 值则不会。

我理解了不更改 {{:failure}} 键的动机。如果该值要将保持不变,我认为 {{stest/abbrev-result}} 应当同样明确测试 {{nil}} 和 {{true}},而不是仅测试 truthy 以保持与 {{stest/check}} 结果的一致性。

0

评论人:djebbz

非常感谢,Michael。最后我采用了一个小的变化,我没有执行 (dissoc x ::stc/ret),而是保留了整个检查结果,因为其中包含了堆栈跟踪、spec/explain-data 映射、缩小的失败用例等。

0

评论者:grzm

看起来 {{abbrev-result}} 应当使用 {{result-type}} 来测试检查是否通过。附上一个补丁来完成这个任务。如果您想让我提供相应的测试,我也很乐意重新提交。

编辑:结论太草率了。我会进行调查并重新提交。为此造成的麻烦深感抱歉。

编辑2:我第一次的判断是正确的。我相当确信我是第一次正确。我认为这个补丁是好的。

0

评论者:gfredericks

请注意,在 test.check 的 master 分支上还有一些未发布的更改,可能会影响在此的最佳做法。(链接:https://github.com/clojure/test.check/blob/master/src/main/clojure/clojure/test/check/results.cljc 文本:此内容)特别。

0
_评论人:grzm_

谢谢,[~gfredericks]。结果协议是值得注意的事物。我认为在 {{abbrev-result}} 的层面上使用 {{result-type}} 是正确的抽象。我认为在 {{make-check-result}} 中对 {{quick-check}} 结果进行装饰时,应当使用 {{Result/passing?}},而不是在 [{{(true? result)}}|https://github.com/clojure/spec.alpha/blob/2824ad49df8deadcb4b75acdf624e732a85b4ac7/src/main/clojure/clojure/spec/test/alpha.clj#L319] 调用中使用。这是否对您有意义?
0

评论者:gfredericks

是的,我认为是这样。但现在我已经审查了规范代码,看到有多少与返回值的附带细节有关(这可能适用于其他test.check用户,不应该让我感到惊讶),我想我将保存Result协议的详细信息进行{{quick-check-2}}。(链接:TCHECK-142 文本:https://dev.clojure.org/jira/browse/TCHECK-142

0
参考:https://clojure.atlassian.net/browse/CLJ-2246 (由 alex+import 报告)
...