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

欢迎!请访问 关于 页面以了解更多关于这是如何工作的信息。

0
test.check

Haskell QuickCheck 允许嵌套 for-all 表达式。当生成值之间存在依赖关系时,这很有用。test.check 也应该允许这样做。

目前,嵌套的 for-alls 总是成功,这有点有害。

我已添加一个补丁来实现此功能。

9 个回答

0

评论由:reiddraper 提出

谢谢 Michael。我很欣赏这个补丁,但我们应该在代码级别细节之前讨论一些设计细节。作为一个相关的问题,我一直想实现类似你的 {{CheckResult}} 类型,但作为一个包含更多字段的记录。这些字段将包含诸如错误发现的纯文本描述、统计信息(类似于 QuickCheck 的 {{collect}}, {{classify}} 等)。我还想编写一个协议,允许基本类型(如布尔值)转换为这种记录。这将类似于 Haskell QuickCheck 的 {{Testable}} 类型类。虽然这是一个技术上的单独问题,但我认为我们可以在解决嵌套 for-alls 的同时解决它,特别是由于嵌套的 for-alls 可以通过仅在生成器级别使用 bind 来模拟。这样可以理解吗?

0

评论由:sperber 提出

当然。

我个人会从这个补丁开始,然后逐步推进,除非你想进行根本性的不同处理而不是添加更多东西。

无论如何,我如何帮忙让它实现呢?

0
by

评论由:reiddraper 提出

这是个好问题。请让我仔细思考并尽快回复您。我也很希望尽快实现这一点。

0
by
_Comment made by: reiddraper_

抱歉延迟了,这是我一直在工作的草图


diff --git a/src/main/clojure/clojure/test/check/properties.clj b/src/main/clojure/clojure/test/check/properties.clj
index 99b5222..139ae9a 100644
--- a/src/main/clojure/clojure/test/check/properties.clj
+++ b/src/main/clojure/clojure/test/check/properties.clj
@@ -8,13 +8,47 @@
 ;   请勿从该软件中删除此注释或任何其他注释。
 
 (ns clojure.test.check.properties
+  (:import clojure.test.check.generators.Generator)
   (:require [clojure.test.check.generators :as gen]))
 
+(defrecord Result [result pass? message stamps])
+
+(defprotocol ToResult
+  (to-result [a]))
+
+(extend java.lang.Object
+  ToResult
+  {:to-result (fn [b]
+                不检查捕获到的异常,这里先这样做
+                (->Result b (not (false? b)) nil nil))})
+
+(extend nil
+  ToResult
+  {:to-result (fn [b]
+               (->Result b false nil nil))})
+
+(extend java.lang.Boolean
+  ToResult
+  {:to-result (fn [b]
+               (->Result b b nil nil))})
+
+(extend Generator
+  ToResult
+  {:to-result identity})
+
+(extend Result
+  ToResult
+  {:to-result identity})
+
+(defn message
+  [m property]
+  (assoc property :message m))
+
 (defn- apply-gen
   [function]
   (fn [args]
-    (let [result (try (apply function args) (catch Throwable t t))]
-      {:result result
+    (let [result (to-result (try (apply function args) (catch Throwable t t)))]
+      {:result (:result result)
        :function function
        :args args})))
 
@@ -29,9 +63,18 @@
   (for-all* [gen/int gen/int] (fn [a b] (>= (+ a b) a)))
   "
   [args function]
-  (gen/fmap
-    (apply-gen function)
-    (apply gen/tuple args)))
+  (gen/bind
+    (apply gen/tuple args)
+    (fn [a]
+      (let [result ((apply-gen function) a)]
+        (cond (gen/generator? result) (gen/fmap (fn [r] (println "foo") (update-in r :args #(conj % a))) result)
+              ;; 注意:在离开这段代码的半夜之前,这是一个快速笔记,
+              这个问题被击中了,因为我们用 {:result ...} 映射包装了结果
+              这应该有条件地执行。
+              我想我们需要两种结果类型,一种是从属性本身返回的结果,以及将 'args' 添加到这个结果上的结果。
+              :else (do (println "bar") (gen/return result)))))
+    ))
+    )
 
 (defn binding-vars
   [bindings]
0

评论由:sperber 提出

看起来没问题。然而,很难理解为什么它能比我的改动更快地达到您所说的目标...

0

评论由:reiddraper 提出

bq. 看起来没问题。然而,很难理解为什么它能比我的改动更快地达到您所说的目标...

公平合理。其中一部分原因是写草稿更容易。当我支持嵌套生成器时,我试图涵盖的主要事项是确保...

  1. 我们还支持收集和返回有关测试的统计数据,类似于 Haskell QuickCheck 中的 {{collect}}
  2. 我们有一种合理的方法将失败的测试返回给用户。目前,在返回映射的 {{:fail}} 和 {{:smallest}} 键中,我们向用户告知失败的参数。由于您可能使用多个生成器(使用 {{prop/for-all}}),它们总是至少被一个向量包装。那么我们对嵌套属性怎么办?我们如何区分同等级别的多个生成器与嵌套属性?或者我们不需要区分?我们的决定是否需要与旧版本向后兼容?

重要的是,我想确保在我们得到一些这些答案之前,我们不承诺支持嵌套属性,对我个人来说,尝试一起尝试这些事情更容易,看看它们会如何结合在一起。

0
_评论者:expez_

我不太想对 for-all 进行嵌套,我更希望它能像 let 一样工作,这样我们就可以引用以前的值。话虽如此,不管哪种解决方案,这都是我对当前测试.check 最大的抱怨,因此任何解决方案都比再一年的休息时间更有吸引力。

这是一个解决方案,来自西南。我确信还有许多其他解决方案,人们迫切需要这个功能,但这个方案是从 Nathan Marz 的 specter 库中获得的


(defmacro for-all+ [bindings & body]
  (let [parts (partition 2 bindings)
        vars (vec (map first parts))
        genned (reduce
                  (fn [curr [v code]]
                  `(gen/bind ~code (fn [~v] ~curr)))
                  (reverse parts))]
                (gen/return ~vars)
    `(prop/for-all [~vars ~genned]
                   ~@body )))
0

评论者:gfredericks

我们一直在思考一个类似的问题(链接:http://dev.clojure.org/jira/browse/TCHECK-81 文本:TCHECK-81),同时还存在一个更酷的 {{for-all}} 变体(链接:https://github.com/gfredericks/test.chuck#properties 文本:在这里)。

0
参考资料:https://clojure.atlassian.net/browse/TCHECK-44(由 alex+import 报告)
...