2014-12-13 10 views
1
(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)) 

:제한된 순서로 일련의 동작에 대한 test.check 생성기를 만드는 방법은 무엇입니까? 두 발생기의 예로서

# (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을 입력해야하며, :edit-board이되기 전에 :create-new-board을 입력해야하고 :edit-comment-text이되기 전에 적어도 하나는 :create-new-*-comment이어야합니다.

위의 코드는 작동하는 것처럼 보이지만 추악합니다. 1) filter-actions-into-logical-order 코드에서 :create-new-user에 대한 특정 예외를 지정하는 방법이 마음에 들지 않습니다. 2) 나는 기본적으로 임의의 동작 목록을 취하고 작업이 순서대로 이해할 때까지 필터링하는 것을 좋아하지 않습니다.

다른 사람들이 test.check를 사용하여 이러한 일련의 동작을 어떻게 생성하는지 궁금합니다. 확실하게 발전기 만 사용하는 방법이 있어야합니까?

+0

아마도이 질문을 http://codereview.stackexchange.com/ –

답변

1

음, filter-into-logical-order 틀림없이 reduce

(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은 내부 생성기에 생성 벡터를 전달하는 것을 지원하지 않으므로 허용되는 값을 알 수 있습니다. 이는 요구 사항에 필요한 구조와 비슷합니다.

+0

으로 옮기거나 복사 할 수 있습니다. 예, 나는 당신이 의존성이있는 일을 어떻게하는지 알아내는 데 어려움을 겪었습니다. 어쩌면 발전기의 구성을 사용하는 대신 제 자신의 발전기를 작성하는 방법을 알아야할까요? –

+0

일 수 있습니다. 상태 모나드가'generators '프레임 워크에서 사용할 수 있다면'order-constrained-elements'베이스 생성기를 만들기 위해 그것을 사용할 수 있습니다. 그러나 그것을 추가하는 방법을 잘 모르겠습니다. 또는 사용 가능한 시퀀스 사이에서 상태를 플러시 할 피팅 포인트가있는 경우 – Magos

2

그것은 gen/bind (예, 먼저 그렇게 gen/bind와 그 크기를 통해 재귀를 사용하여 작업 목록의 크기를 생성 사용하는 재귀 발생기이 일을 너무 단단하지 않다 당신의 각 단계에서 이전에 생성 된 작업이). 이 접근 방식의 가장 큰 단점은 이 줄어들 기는 다소 어려우므로 결국 거의 축소 할 수없는 긴 일련의 작업이 끝나게 될 것입니다.

나는 이것을 위해 더 좋은 것을 생각해 내고 싶다.