请在 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}} 的返回值,该函数返回被评估为真假的属性值,以确定通过或失败。由于非真值只能是 {{false}} 或 {{nil}},观察它并没有提供很多信息(尽管 {{:failure}} 键下可能有一个例外,这会更有信息性)。

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

0

评论由:djebbz

我仍然不明白为什么你不认为这是一个bug。`stest/check` 的文档字符串说 ":failure 任意测试失败"。我期望只有当测试失败时才有 `:failure` 键(因此使用“可选”),并且包含一些有价值的信息。

我使用 `stest/abbrev-result` 来显示 `stest/check` 的输出,它期望 `:failure` 为真以显示所有有价值的失败信息。如果 `stest/check` 返回 `false`,这是一个我认为的bug。`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}},而不是测试有意义的值以保持与 {{stest/check}} 的结果一致性。

0

评论由:djebbz

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

0

评论者:grzm

看起来 {{abbrev-result}} 应该使用 {{result-type}} 来测试检查是否通过。附件是一个补丁,实现了这一点。如果需要伴随的测试,我很乐意再次提交。

编辑:嗯,我太急了。我将进行调查并再次提交。抱歉制造的噪音。

编辑2:我最初考虑是不正确的。我相当确定我第一次是正确的。我认为这个补丁是好的。

0

评论人:gfredericks

请注意,test.check的主要分支上可能有未发布的变化,可能会影响这里的最佳做法。(链接:[https://github.com/clojure/test.check/blob/master/src/main/clojure/clojure/test/check/results.cljc](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](https://github.com/clojure/spec.alpha/blob/2824ad49df8deadcb4b75acdf624e732a85b4ac7/src/main/clojure/clojure/spec/test/alpha.clj#L319)] 调用。这个对您来说有道理吗?
0

评论人:gfredericks

是的,我认为是这样。但现在我已经审查了规范代码,并看到有多少关于返回值的不确定性是被依赖的(这也许对其他test.check用户也是如此,而且不应该令我惊讶),我认为我将为快速检查2({{quick-check-2}})保存结果协议详情。(链接:TCHECK-142 文本:https://dev.clojure.org/jira/browse/TCHECK-142)。

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