Fork me on GitHub
#clojure-spec
<
2019-07-09
>
arohner13:07:08

I have an s/keys with a key of type uuid?. I have a generative test where I generate a few hundred records, and insert them into postgres, where the uuid uniqueness constraint is checked. Occasionally the test fails due to duplicate uuids. Is there a way to tell spec/test.check to only generate unique uuids?

ghadi14:07:14

there are ways of generating unique data within spec/t.c. @arohner but for this usecase I would dedupe between generation and inserting records

kenny15:07:03

It seems useful to have s/with-gen be passed the generator for the spec it is overriding. Often I find myself generating values from the spec's gen and then fmap'ing to ensure certain constraints are met.

kenny15:07:36

It'd also be useful to have a variant of s/and that doesn't pass the conformed value to s/and predicates. We have a lot of this in our specs:

(s/and
  (s/keys :req [:metric/tags :metric/lower-bound :metric/upper-bound])
  #(metric-tags-valid? (s/unform ::base-metric %))
  #(metric-bounds-valid? (s/unform ::base-metric %)))

misha16:07:27

sometimes changing order inside s/and works

kenny16:07:40

These such-that errors are quite frustrating because they provide no info:

Error printing return value (ExceptionInfo) at clojure.test.check.generators/fn (generators.cljc:417).
Couldn't satisfy such-that predicate after 100 tries.
clojure.lang.ExceptionInfo: null #:clojure.error{:phase :print-eval-result}
	at clojure.main$repl$read_eval_print__9068.invoke(main.clj:419)
clojure.lang.ExceptionInfo: Couldn't satisfy such-that predicate after 100 tries. {:pred #object[clojure.spec.alpha$gensub$fn__1876 0x71807ca2 "clojure.spec.alpha$gensub$fn__1876@71807ca2"], :gen #clojure.test.check.generators.Generator{:gen #object[clojure.test.check.generators$gen_pure$fn__2974 0x39e7d8ab "clojure.test.check.generators$gen_pure$fn__2974@39e7d8ab"]}, :max-tries 100}
At the very least, including the predicate form would be extremely helpful.

misha16:07:34

@kenny you can sometimes enhance that by naming your anon fns

misha16:07:14

e.g. (fn f1 [x] (metric-tags-valid? (s/unform ::base-metric x))) instead of #(metric-tags-valid? (s/unform ::base-metric %))

misha16:07:45

it might show up in stacktrace as something like clojure.spec.alpha$gensub$f1@71807ca2 instead of clojure.spec.alpha$gensub$fn__1876@71807ca2

kenny17:07:58

Yeah I suppose I could do that. It'd be great if there was a tighter integration between spec and test.check so I don't need to do that.

kenny21:07:44

clojure.spec.gen.alpha/gen should have up to 3 args (http://clojure.github.io/test.check/clojure.test.check.generators.html#var-generate) when it only has one.