首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何为约束顺序中的一系列操作创建test.check生成器?

如何为约束顺序中的一系列操作创建test.check生成器?
EN

Stack Overflow用户
提问于 2014-12-14 06:10:29
回答 2查看 329关注 0票数 1
代码语言:javascript
复制
(require '[clojure.test.check.generators :as gen])

(def ACTIONS
  {:create-new-user #{}
   :edit-user #{:create-new-user}
   :create-new-board #{:create-new-user}
   :edit-board #{:create-new-board}
   :create-new-anonymous-comment #{:create-new-board}
   :create-new-signed-comment #{:create-new-board}
   :edit-comment-text #{:create-new-anonymous-comment :create-new-signed-comment}
   :edit-comment-text-and-flip-anonymity #{:create-new-anonymous-comment :create-new-signed-comment}
   :flip-anonymity #{:create-new-anonymous-comment :create-new-signed-comment}
   :vote-comment-up #{:create-new-anonymous-comment :create-new-signed-comment}
   :vote-comment-down #{:create-new-anonymous-comment :create-new-signed-comment}})

(def actions (-> ACTIONS keys vec gen/elements gen/vector))

(defn filter-actions-into-logical-order [as]
  (let [seen (atom #{})]
    (filter
     (fn [v]
       (let [required (get ACTIONS v)
             valid? (or (some? (some required @seen)) 
                        (and (empty? @seen) (= v :create-new-user)))]
         (when valid?
           (swap! seen conj v)
           true)))
     as)))

(def ordered-actions (gen/fmap #(-> % filter-actions-into-logical-order vec)  actions))

以这两个生成器为例:

代码语言:javascript
复制
# (last (gen/sample actions 100))
[:edit-user :vote-comment-down :flip-anonymity :vote-comment-down :vote-comment-down :vote-comment-up :edit-user :create-new-anonymous-comment :edit-board :create-new-signed-comment :vote-comment-up :edit-comment-text-and-flip-anonymity :edit-user :create-new-signed-comment :edit-user :edit-user :vote-comment-down :edit-user :vote-comment-down :create-new-user :vote-comment-down :create-new-user :create-new-user :edit-comment-text-and-flip-anonymity :create-new-user :edit-comment-text-and-flip-anonymity :create-new-anonymous-comment :edit-comment-text :create-new-board :vote-comment-down :flip-anonymity :create-new-signed-comment :vote-comment-up :create-new-user :create-new-signed-comment :edit-user :create-new-user :create-new-board :vote-comment-down :create-new-board :create-new-board :create-new-board :edit-board :edit-comment-text-and-flip-anonymity :edit-user :edit-comment-text :create-new-signed-comment :vote-comment-up :edit-comment-text-and-flip-anonymity :flip-anonymity :create-new-anonymous-comment :create-new-anonymous-comment :edit-board :create-new-signed-comment :edit-comment-text-and-flip-anonymity :edit-board :vote-comment-up :edit-comment-text :create-new-board :edit-comment-text-and-flip-anonymity :create-new-board :vote-comment-down :edit-comment-text-and-flip-anonymity :vote-comment-up :create-new-user :vote-comment-up :edit-comment-text :edit-board :edit-comment-text-and-flip-anonymity :flip-anonymity :edit-board :create-new-anonymous-comment :flip-anonymity :create-new-signed-comment :edit-user :edit-comment-text-and-flip-anonymity :edit-comment-text :edit-comment-text :create-new-user :flip-anonymity :edit-user :vote-comment-up :edit-user :create-new-user :edit-comment-text :edit-comment-text :flip-anonymity :edit-comment-text :edit-board :flip-anonymity :edit-board :edit-comment-text :edit-user :create-new-user :flip-anonymity]


# (last (gen/sample ordered-actions 100))
[:create-new-user :edit-user :edit-user :create-new-board :edit-board :edit-user :create-new-anonymous-comment :edit-comment-text :edit-board :edit-user :edit-user :vote-comment-up :edit-comment-text :create-new-signed-comment :edit-comment-text :create-new-board :edit-comment-text :edit-comment-text :edit-comment-text :vote-comment-up :vote-comment-up :edit-board :edit-comment-text-and-flip-anonymity :create-new-signed-comment :create-new-anonymous-comment :create-new-signed-comment :edit-user :create-new-anonymous-comment :edit-board :create-new-board :create-new-anonymous-comment :create-new-board :flip-anonymity :create-new-anonymous-comment :edit-board :vote-comment-up :vote-comment-down :edit-board :edit-comment-text :edit-user :edit-comment-text :flip-anonymity :create-new-signed-comment :vote-comment-up :edit-comment-text-and-flip-anonymity :vote-comment-up :create-new-signed-comment :edit-comment-text :create-new-signed-comment :create-new-anonymous-comment :edit-board :create-new-anonymous-comment]

ACTIONS是一个映射,其中键是操作的名称,值是该操作的(基于OR的)依赖项。例如,您必须先执行:create-new-user,然后才能执行任何操作,必须先执行:create-new-board,然后才能执行:edit-board,并且必须至少有一个:create-new-*-comment才能执行:edit-comment-text

上面的代码似乎可以工作,但它很难看。1)我不喜欢filter-actions-into-logical-order代码必须对:create-new-user有一个特定的异常。2)我不喜欢我基本上采用随机操作的列表,并将其过滤,直到这些操作有顺序的意义。

我想知道其他人是如何使用test.check生成这样的一系列动作的?肯定有一种只使用生成器就能做到这一点的方法?

EN

回答 2

Stack Overflow用户

发布于 2015-12-29 10:02:34

使用使用gen/bind的递归生成器来实现这一点并不太难(例如,首先生成操作列表的大小,然后使用gen/bind在该大小上使用递归,以便在每一步都有先前生成的操作)。这种方法的最大缺点是,gen/bind在收缩方面的工作相当糟糕,因此您可能会得到几乎根本不能收缩的长序列操作。

我真的很想为此想出更好的办法。

票数 2
EN

Stack Overflow用户

发布于 2014-12-16 08:23:03

可以说,如果改用reducefilter-into-logical-order可能会更干净

代码语言:javascript
复制
(defn filter-into-logical-order [as]
  (last (reduce
         (fn [[seen accepted-as] action]
           (let[needed (get ACTIONS action)]
             (if (or (empty? needed) (some seen needed))
               [(conj seen action) (conj accepted-as action)]
               [seen accepted-as]))
           )
         [#{} []]
         as)))

但这仍然为我提供了大约30%的空向量,而且它不是一个生成器。不过,我不确定文档中的组合子是否真的支持您想要的内容。gen/vector似乎不支持将构造中的向量传递给它的内部生成器,这样它就可以知道允许什么值,这是您的需求所需的某种结构。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27464157

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档