gpt4 book ai didi

testing - 如何以一对多的方式编写 clojure.test.check 生成器?

转载 作者:行者123 更新时间:2023-11-28 19:49:46 24 4
gpt4 key购买 nike

假设我有一个生成器 users-gen,它生成一组 1 个或多个用户。另一个名为 user-actions-gen 的参数化生成器接受一个或多个用户的序列,并生成这些用户可能执行的一系列操作。

(def user-gen 
;; generates a user
...)

(def users-gen
;; sequences of 1 or more users
(gen/such-that not-empty (gen/vector gen/users))

(defn user-actions-gen [users]
;; a action performed by some user from the `users argument
...)

如果我想为 users-gen 生成的单个用户序列生成单个操作,那么很简单,直接将 users-gen 生成/绑定(bind)到 user-actions-gen 即可。

但是,我想从相同的用户序列中生成许多操作。我遇到这个问题是因为我基本上只是想说“这是状态,让任何随机 Action 进来,让我们将 Action 应用到状态,让我们确认状态仍然有效;对所有 Action 都这样做。 “我有以下代码。

(defspec check-that-state-is-always-valid
100
(let [state-atm (atom {})]
(prop/for-all
[[actions users]
(gen/bind users-gen
(fn [users]
(gen/tuple
(gen/vector (user-actions-gen users))
(gen/return users))))]
(doseq [action actions
:let [state (swap! state-atm state-atm-transform-fx action)]]
(is (state-still-valid? state))))))

这类作品。问题是:

  1. 它似乎完全评估了 doseq 而不是在第一个错误时停止
  2. 它看起来有点不对劲。代码到处都是,它的作用并不完全明显。
  3. 似乎 user-actions-gen 应该采用 users-gen 的生成器,而不是 users-gen 的已实现用户值?这对可组合性有帮助吗?请注意,我不想将它们放在一起,因为 users-gen 可能对其他生成器有用。

所以,回顾一下。我从one 生成器获取单个生成值并将其作为参数传递给多个 生成器。我该如何以更具吸引力/优雅的方式来做到这一点?

最佳答案

您可能想查看最新版本的 test.check (0.9.0)。它现在在生成器命名空间中包含一个 let,这使得组合生成器变得轻而易举:

https://github.com/clojure/test.check/blob/master/src/main/clojure/clojure/test/check/generators.cljc#L1452

这样做的缺点是您仍然不能直接在 prop/for-all 中执行此操作(显然是由于向后兼容的原因)。

我推荐的替代方案是使用 test.chuck (它是由 test.check 的当前维护者编写的)。它确实有一个for-all,它的绑定(bind)形式就像generators/let 一样工作。这是我发现的最干净的方法,并且效果很好。

关于testing - 如何以一对多的方式编写 clojure.test.check 生成器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23685366/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com