Ste*_*gle 5 testing clojure generative-testing
我们假设我有一个生成器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
...)
Run Code Online (Sandbox Code Playgroud)
如果我想为users-gen生成的单个用户序列生成单个动作,那么它很简单,只需直接将gen/bind user-gen转换为user-actions-gen.
但是,我想从相同的用户序列生成许多操作.我有这个问题,因为我基本上只是想说"这是状态,让任何随机动作进来,让我们将动作应用到状态,让我们确认状态仍然有效;为所有动作执行此操作. " 我有以下代码.
(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))))))
Run Code Online (Sandbox Code Playgroud)
这种作品.问题是:
所以,回顾一下.我从一个生成器获取一个生成的值,并将其作为参数传递给多个生成器.我如何以更有吸引力/更优雅的方式做到这一点?
我将对您当前正在做的事情进行两项主要更改:
将内联取出gen/bind到一个新的生成器中,暂时命名(另请注意,我交换了结果中和 的users-and-actions-gen顺序以匹配名称):usersactions
(def users-and-actions-gen
(gen/bind users-gen
(fn [users]
(gen/tuple
(gen/return users)
(gen/vector (user-actions-gen users))))))
Run Code Online (Sandbox Code Playgroud)不要使用原子来测试不需要它的东西。您可以生成一个惰性状态序列,然后测试它们是否都具有您正在寻找的属性。这样它就会很好地读取并且具有您正在寻找的短路属性:
(defspec check-that-state-is-always-valid
100
(prop/for-all [[users actions] users-and-actions-gen]
(is (every? state-still-valid?
(reductions (fn [state action]
(state-atm-transform-fx state action))
{} actions)))))
Run Code Online (Sandbox Code Playgroud)除了这两个更改之外,我不确定您是否可以真正改进您正在做的事情。我认为你的users-and-actions-gen描述相当具体。它可以稍微概括,但我不确定概括是否有用(它本质上是一个受限的bind)。我上面提出的建议应该可以解决您的问题(1)和(2),但我认为(3)并不是真正的问题。
| 归档时间: |
|
| 查看次数: |
771 次 |
| 最近记录: |