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

评论者:reiddraper

这是个好问题。让我考虑一下,尽早给您回复。我也希望尽快促成此事。

0
评论者: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]
+               ([] not (false? b)) nil nil))})
+(extend nil
+
+               ([] false nil nil))})
+  ToResult
+  {:to-result (fn [b]
+(extend java.lang.Boolean
+
+               ([] b b nil nil))})
+  ToResult
+  {:to-result (fn [b]
+(extend Generator
+
+  {:to-result identity})
+  ToResult
+(extend Result
+
+(defn message
+  ToResult
+(extend Result
+
+  [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})))
   (for-all* [gen/int gen/int] (fn [a b] (>= (+ a b) a)))
 
@@ -29,9 +63,18 @@
   "
   [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)
-              -highlighted code is from: https://github.com/username/repository/commit/commit_hash, and you cannot view the
-              charset is not supported.
-               Highlighted code is from: https://github.com/username/repository/commit/commit_hash, and you
-              Highlight light code is highlight code.
-              highlighted code is highlighted code.
-              Highlight is highlighted code.
-              Highlight the highlighted code is highlighted code.
-              Highlight is highlighted code.
 
 (defn binding-vars
   [绑定]
0

评论者:sperber

看起来没问题。然而,很难理解为什么它会比你提出的补丁更快地达到你想要的目的...

0

评论者:reiddraper

bq. 看起来没问题。然而,很难理解为什么它会比你提出的补丁更快地达到你想要的目的...

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

  1. 我们也支持即将到来的收集和返回测试统计的能力,类似于 Haskell QuickCheck 中的 {{collect}}
  2. 我们有合理的方式将失败的测试返回给用户。目前,在返回映射的 {{:fail}} 和 {{:smallest}} 键中,我们告诉用户失败的参数。它们总是封装在一个或多个向量中,因为您可能使用多个生成器来使用 {{prop/for-all}}。我们如何处理嵌套属性?我们如何区分在“相同级别”上的多个生成器与嵌套属性?或者我们不需要区分?我们做出的任何决定是否都能向后兼容?

重点是,我想确保在我们得到一些答案之前,不要让我们的承诺局限于嵌套属性,对我个人来说,尝试一起玩这些事情更容易,看看它们如何相互匹配。

0
评论者为:expez_

我真的不希望必须嵌套 for-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
by

评论者:gfredericks

我们已经在(link: http://dev.clojure.org/jira/browse/TCHECK-81 文本: TCHECK-81) 中思考过类似的问题,同时还有一个更复杂的 {{for-all}} 变体(link: https://github.com/gfredericks/test.chuck#properties 文本: 这里)。

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