Fork me on GitHub
#clojure-spec
<
2018-01-30
>
rafael20:01:50

I'm trying to pass :gen overrides for clojure.spec.test.alpha/check, but I get the sense my understanding of the documentation.

rafael20:01:08

I expected the following to succeed:

(defn foo [k]
  (if (keyword? k) :k :nope))

(def my-kw? (partial instance? Keyword))

(s/fdef foo
        :args (s/cat :a-keyword my-kw?)
        :ret #{:k})

(spec.test/check `foo {:gen {`my-kw? (gen/return :kw)}})

rafael20:01:05

I'm trying to pass in a generator for the my-kw? spec, but it fails with the cause "Unable to construct gen at: [:a-keyword] for: my-kw?"

rafael20:01:00

Is overriding generators on the call to check possible and I'm getting some detail wrong, or did I just misunderstand the docs for check and there is no way to override generators like that?

Alex Miller (Clojure team)20:01:31

the values in that map should be 0-arg functions returning a generator

Alex Miller (Clojure team)20:01:48

so change (gen/return :kw) to #(gen/return :kw)

Alex Miller (Clojure team)20:01:17

although now that I back up a bit, I don’t think you can do what you’re trying to do with my-kw? either

Alex Miller (Clojure team)20:01:43

you should instead register a named spec instead of my-kw?:

Alex Miller (Clojure team)20:01:46

(s/def ::my-kw keyword?) and then use ::my-kw instead of my-kw? and as the key in the gen map

Alex Miller (Clojure team)20:01:31

Putting it all together:

user=> (require '[clojure.spec.alpha :as s] [clojure.spec.test.alpha :as stest] [clojure.spec.gen.alpha :as gen])
nil
user=> (defn foo [k] (if (keyword? k) :k :nope))
#'user/foo
user=> (s/def ::my-kw keyword?)
:user/my-kw
user=> (s/fdef foo :args (s/cat :a-keyword ::my-kw) :ret #{:k})
user/foo
user=> (stest/check `foo {:gen {::my-kw #(gen/return :kw)}})
({:spec #object[clojure.spec.alpha$fspec_impl$reify__2451 0x6c25e6c4 "[email protected]"], :clojure.spec.test.check/ret {:result true, :num-tests 1000, :seed 1517344332731}, :sym user/foo})

rafael18:01:15

That works. I had tried the 0-arg generator function, but I was missing the fact that the spec ident had to be a keyword. Thank you!

jqmtor22:01:34

hey all, I've been meddling with spec and I came across something I don't know how to represent. I want to create a spec for the s/keys spec itself and I have this:

(s/cat :spec-kind #{`s/keys}
         :keys      (s/+ (s/cat :mandatory+qualified? #{:req :opt :req-un :opt-un}
                                :keys                 (s/coll-of keyword? :kind vector?))))
the problem is that the keys :req :opt and so on can be repeated. is there any way to avoid this? (any other unrelated suggestion is also welcome)

jqmtor22:01:16

great, thanks! missed that when looking through the api

eriktjacobsen22:01:47

I'm running into the same wall described at https://groups.google.com/d/msg/clojure/i8Rz-AnCoa8/OEg04fbKBwAJ where we'd like to resolve a symbol for a multi-fn in clojurescript but apparently cannot. is this being looked into? that thread died.