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

欢迎!有关本站如何运作的更多信息,请参见 关于 页面。

0
Spec

当尝试手动将 clojure.test 和 spec 与 fdef'ed 函数连接起来时,我意识到 spec.test/check 为失败的测试返回一个包含(链接::failure false)的映射。我几乎确定它应该返回 true,因为 spec.test/abbrev-result 将作为参数接收 spec.test/check 的返回值,并测试 :failure 的值。我无法创建一个 spec.test/check 为失败的测试返回(链接::failure true)的情况。为了信息起见,对于通过测试,它返回一个不带 :failure 键的映射。

以下是一个简单的复现案例

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

(s/fdef foo-fn)

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

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

(defn foo-fn (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

我还是不明白为什么你不会将其视为一个错误。函数 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
  "给定一个检查结果,返回一个适合用于总结的简略版本。"
suitable for summary use."
  [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}} 的值都将提供额外的详细信息,而 falsey 的 {{: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的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

是的,我想是这样的。但现在我已经审查了spec代码,看到有多少关于返回值的偶然细节被依赖(这可能适用于其他test.check用户,这也并不会让我感到惊讶),我认为我将在{{quick-check-2}}中保存结果协议的细节(链接:TCHECK-142 文本:https://dev.clojure.org/jira/browse/TCHECK-142)。

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