1

在这个问题和那里引用的博客文章之后,有没有理由prop/for-all不直接加入这种能力?例如:

(require '[clojure.test.check.generators :as gen])
(require '[clojure.test.check.properties :as prop])
(require '[clojure.test.check.clojure-test :refer :all])

(defspec some-props-test
  (prop/for-all [n (gen/choose 1 10)
                 v (gen/vector gen/int n) ;; treat n like its produced value
                 e (gen/element v)]
    ... do stuff with n, v & e ...
  ))

基本上,我想在另一个生成器中重用一个生成器生成的,然后引用实际测试代码中生成的两个值。这将本质上扩展糖/魔术,for-all以允许在宏提供的 let-like 块中引用生成的值,因为它在下面的表达式块中工作。

请让我知道我是否遗漏了其他使这成为可能的东西,或者由于某种原因实施起来没有意义。

4

2 回答 2

6

我同意这个功能可能比for-all目前的功能更有用。它没有被改变的主要原因是为了向后兼容(尽管使用旧样式的代码诚然不会破坏,它不会像以前那样缩小)。

但是你有更多的选择,而不仅仅是单子:

  • gen/let,它使用let-style 绑定(它不是替代品,for-all但您可以一起使用它们)
  • com.gfredericks.test.chuck.generators/fortest.chuck辅助库中定义——它就像一个更高级的版本gen/let
  • com.gfredericks.test.chuck.properties/for-all, 在同一个库中,它for-all
于 2015-12-29T00:31:49.847 回答
0

我在该系列中发现了后面的博客文章,它完全清除了 的用法test.check(需要先阅读一些内容才能理解monads它)。所以首先可以声明 monad:

(require '[clojure.algo.monads :as m])

(m/defmonad gen-m
    [m-bind gen/bind
     m-result gen/return])

(def vector-and-elem
  (m/domonad gen-m
    [n (gen/choose 1 10)
     v (gen/vector gen/int n)
     e (gen/element v)]
    [n v e]))

gen-mmonad 允许引用将为先前声明的生成器生成的值。

然后,可以直接在for-all调用中使用:

(defspec some-props-test
  (prop/for-all [[n v e] vector-and-elem]
    ... do stuff with n, v & e ...
  ))

您可以通过向量(或您喜欢的映射)在 monad 调用生成的表达式中传递与您的约束检查代码相关的所有值,然后对其进行gen-m解构以获得您需要的内容。

不过,如果这在 中自动完成,那就太好了for-all,但这已经足够好了。

于 2015-12-29T00:00:32.890 回答