clojure-spec

About: http://clojure.org/about/spec Guide: http://clojure.org/guides/spec API: https://clojure.github.io/spec.alpha/clojure.spec.alpha-api.html
2021-05-24T15:45:22.042100Z

Personally I recommend writing two generation functions, one that takes a generation depth and generates a full data structure to that depth, and another that takes a generation depth and generates a "narrow" structure to the given depth. This way you can test with the first one to a low depth to see "wide" structure generation, and use a much higher generation depth for the narrow one, using a weighted rng to choose which one to generate when using a with-gen form in the spec.

2021-05-24T15:45:32.042300Z

@adam678

2021-05-24T15:48:51.043Z

Or as you've noted, recursive-gen already provides a reasonable solution, in that case you can also use that with spec's facilities to wrap something with a custom generator.

👍 1
2021-05-24T16:01:57.043300Z

(require '[clojure.test.check.generators :as gen])

(s/def ::bool
  boolean?)

(def data-gen (gen/recursive-gen gen/vector gen/boolean))

(s/def ::vec
  (s/with-gen
    (s/coll-of ::data)
    (gen/vector data-gen)))

(s/def ::data
  (s/with-gen
    (s/or :bool ::bool
          :vec ::vec)
    data-gen))

2021-05-24T16:10:33.044200Z

For reference, the clojure spec generators are just a reexport of the functions in clojure.test.check.generators, which means that you can use them interchangeably.

alexmiller 2021-05-24T16:24:01.045Z

well, almost interachangeably - most of the spec apis actually take a no-arg function that returns a generator instead of a generator (to allow for dynamic require/invoke)

lassemaatta 2021-05-25T15:42:15.045400Z

I remember wondering why e.g. with-gen accepts a "generator returning function" instead of the generator itself; can you clarify what you mean by that "dynamic require/invoke" functionality? Something to do with requiring additional namespaces within the function but only if the generator is actually invoked (e.g. in generative testing)?

alexmiller 2021-05-25T15:44:55.045600Z

yes, that

alexmiller 2021-05-25T15:45:21.045800Z

by putting it in a thunk, we can avoid dynaloading the test.check.generators ns

lassemaatta 2021-05-25T15:46:45.046Z

I see, thank you

2021-05-24T16:31:54.045300Z

Oh that's good to know. Thanks for the heads up on that.