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

欢迎!请参阅 关于 页面,以获得有关如何操作的更多信息。

0
test.check

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

目前,嵌套的 for-all 总是成功,这在某种程度上是有害的。

我已经添加了一个实现此功能的补丁。

9 个答案

0

评论者:reiddraper

感谢迈克尔。我欣赏这个补丁,但在我们深入到代码细节之前,有一些设计细节我们可以讨论。作为一个单独但相关的问题,我希望能实现像你的 {{CheckResult}} 类型这样的东西,但是作为一个具有更多字段的记录。这些字段将保持查找任何错误的 plain-text 描述,统计数据(类似于 QuickCheck 的 {{collect}}、{{classify}} 等)。我还想编写一个协议,使得基本类型如布尔值可以被转换为这个记录。这类似于 Haskell QuickCheck 的 {{Testable}} 类型类。虽然这是一个技术上的单独问题,但我认为我们应该在与可嵌套的 for-all 一起解决问题,特别是由于嵌套的 for-all 可以通过在生成器级别使用 bind 来模拟。这说得通吗?

0

评论者:sperber

当然。

我个人会从这个补丁开始,然后继续前进,除非你想进行根本性的改变而不是添加更多内容。

无论如何,我怎么能帮助让它成为现实呢?

0
by

评论者:reiddraper

这是个很好的问题。让我思考一下,尽快回复你。我也希望能尽快实现这个功能。

0
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)
+              ;;; 注意:在我离开这段代码之前,这里快速做一下笔记,
+              ;; 这个 :else 被调用是因为我们正在将结果
+              ;;; 包装在一个带有关联的 {:result ...} 映射中。
+              ;;; 我想我们应该有两个结果类型,一个结果是属性本身返回的,
+              ;;; 另一个结果将 'args' 放在这个结果之上。
+              :else (do (println "bar") (gen/return result)))))
+    ))
 
-  (defn binding-vars
   [绑定]
0

评论者:sperber

看起来不错。然而,很难理解这为什么能够比我的补丁更快地让你达到你说的地方...

0

评论者:reiddraper

bq. 看起来不错。然而,很难理解这为什么能够比我的补丁更快地让你达到你说的地方...

公平。其中一部分原因是,我写草图更容易。在支持嵌套生成器时,我主要尝试确保...

  1. 我们还支持即将到来的功能:收集和返回有关测试的统计信息,类似于Haskell QuickCheck中的collect
  2. 我们有合理的退回失败测试给用户的方法。目前,在返回映射的{{:fail}}和{{:smallest}}键中,我们告诉用户失败的参数。由于可能使用多个生成器({{prop/for-all}}),因此它们总是至少包含一个向量。对于嵌套属性我们怎么办?我们如何区分'同一级别'上的多个生成器,与嵌套属性?或者我们不需要区分?我们做出的任何决定都能与旧版本兼容吗?

重点是,我想确保我们在得到这些答案之前不要将自己局限于嵌套属性,对我来说,尝试将它们一起玩并观察它们如何配合更容易。

0
_评论者:expez

我真的不想嵌套地进行all测试,我更希望它像let一样工作,我们可以引用前值。尽管如此,无论哪种解决方案,这都是我目前test.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)))
                    (gen/return ~vars)
                   (reverse parts))]
    `(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 报告)
...