Skip to content

Instantly share code, notes, and snippets.

@gfredericks
Created October 24, 2015 02:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gfredericks/cf024c0fd5d2824b034e to your computer and use it in GitHub Desktop.
Save gfredericks/cf024c0fd5d2824b034e to your computer and use it in GitHub Desktop.
test.check bind example for event sequences
;;
;; Example of using bind to generate a sequence of events, where each
;; event can be generated based on the previous events
;;
(ns user
(:require [clojure.test.check.generators :as gen]))
(def init-state
{:ids #{}})
(defn gen-event
[{:keys [ids]}]
(let [gen-create (gen/fmap #(list 'create %)
(gen/such-that #(not (ids %))
gen/nat))]
(if (empty? ids)
gen-create
(let [gen-update (gen/fmap #(list 'update %)
(gen/elements ids))]
(gen/frequency [[3 gen-update]
[1 gen-create]])))))
(defn update-state
[state ev]
(if (= 'create (first ev))
(update state :ids conj (second ev))
state))
(def gen-events
(gen/bind gen/nat
(partial
(fn self [state ev-count]
(if (zero? ev-count)
(gen/return ())
(gen/bind (gen-event state)
(fn [event]
(gen/fmap #(cons event %)
(-> state
(update-state event)
(self (dec ev-count))))))))
init-state)))
;; (gen/generate gen-events)
;; => ((create 6))
;; (gen/generate gen-events)
;; =>
;; ((create 5)
;; (create 13)
;; (update 5)
;; (update 5)
;; (update 13)
;; (update 5)
;; (create 4)
;; (update 5)
;; (update 13)
;; (update 5)
;; (create 27)
;; (create 2)
;; (update 2)
;; (update 2)
;; (update 4)
;; (update 5)
;; (update 13)
;; (update 4)
;; (update 4)
;; (create 11)
;; (update 2)
;; (update 4)
;; (update 4)
;; (update 11)
;; (update 5)
;; (update 5)
;; (update 11)
;; (update 2)
;; (update 27))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment