Fork me on GitHub
#clojure-spec
<
2017-10-11
>
nwjsmith00:10:41

I’m having trouble figuring out which generator is causing the error

bfabry00:10:00

@nwjsmith one option would be to walk the registry using s/registry and try and generate an example for each one until you fail

bfabry00:10:19

I believe there's a jira open to figure out a way to add the offending spec to the error message you're seeing

gfredericks00:10:10

s/and is a common culprite

gfredericks00:10:24

the way to add the offending spec to the error message is implemented in the latest alpha of test.check, but I doubt has been incorporated into spec. I assume there's an open ticket for that.

nwjsmith00:10:43

I’ve narrowed my current run-in with that error down to this:

(s/def ::header-name
  (s/with-gen
   (s/and string?
          (complement string/blank?)
          utilities.string/lower-case?
          utilities.string/ascii?)
   #(gen/fmap (comp string/lower-case (partial string/join "-"))
              (gen/vector (gen/not-empty (gen/string-ascii))
                          1
                          100))))

nwjsmith00:10:26

Ah, figured it out

nwjsmith00:10:41

my utilities.string/ascii? function is broken

msolli07:10:27

I’m specing a function that calls another function, stubbing out that second function with instrument. When I’m doing stest/check on the function, it’s really slow. Takes ~30 s with :num-tests 1000. With num-tests 100, it’s sub-second. What gives?

(require '[clojure.spec.alpha :as s])
(require '[clojure.spec.test.alpha :as stest])

(defn fetch-foo-from-somewhere
  [a]
  [,,,])

(defn get-foo
  [b]
  (fetch-foo-from-somewhere b))

(s/def ::foo string?)
(s/fdef fetch-foo-from-somewhere
        :args (s/cat :a any?)
        :ret ::foo)
(s/fdef get-foo
        :args (s/cat :b any?)
        :ret ::foo)

(stest/instrument `fetch-foo-from-somewhere {:stub #{`fetch-foo-from-somewhere}})

(stest/summarize-results (stest/check `get-foo {:clojure.spec.test.check/opts {:num-tests 1000}}))

gfredericks10:10:17

@msolli how about {:num-tests 1000 :max-size 100}?

msolli11:10:15

Yeah, that took the time down to ~4 s.

msolli11:10:02

So I understand :max-size somehow controls the way generated values “grow” as the number of tests increase. How does this explain why larger sizes takes so much more time?

gfredericks11:10:29

probably stemming from the use of any? in this case

gfredericks11:10:01

I suppose you could argue that the generator underlying any? should be designed to never get very big

msolli11:10:49

Ah, I see. I’m just getting into Spec, and I’m following along to https://clojure.org/guides/spec#_combining_code_check_code_and_code_instrument_code. It seemed strange that the official docs endorse something this slow.

msolli11:10:42

I can confirm that the values generated for any? really do become huge.

msolli11:10:53

So I guess it’s the GC-ing of those large objects that is the bottleneck.

Alex Miller (Clojure team)11:10:02

There are some tickets and work to do in this area still

Alex Miller (Clojure team)11:10:20

@gfredericks the most critical fix was the bug in s/coll-of that went into the spec release last week actually. That was the cause of one set of problems (not the one here though).

gfredericks11:10:38

I can't see anything that looks particularly relevant in the last 6 months of commits

gfredericks11:10:18

oh was it generating a bunch of stuff and throwing it away?

msolli11:10:53

The conj, well, enjoy yourselves! And thanks for the explanation and all the great work you’re doing.

gfredericks11:10:52

@alexmiller after reading the ticket, I assume CLJ-2103 is what you were referring to Any thoughts (ha!) about any?? The underlying gen/any-printable in test.check could have its size scaled down. I feel like that would make it more useful for almost any conceivable use case.

Alex Miller (Clojure team)11:10:57

Yeah that would be good

gfredericks11:10:04

although now that I think about it, making sizing better in collections and gen/recursive-gen might take care of the gen/any-printable problem

mmer13:10:43

Is there anyway to get the context of a element being validated by a spec. I need to get hold of the overall datastructure that is being validate by a set of specs so that I can do some cross validation in my own predicate?

taylor14:10:06

I commented on your Stack Overflow question too. I think maybe the solution to your problem is to enforce that invariant from your outer spec instead of your inner spec?

taylor14:10:47

posted example on SO

taylor14:10:52

(s/def ::tag string?)

(s/def ::inner (s/keys :req-un [::tag]))

(s/def ::outer
  (s/and
    (s/keys :req-un [::inner ::tag])
    #(= (:tag %) ;; this tag must equal inner tag
        (:tag (:inner %)))))

(s/conform ::outer {:tag "y" ;; inner doesn't match outer
                    :inner {:tag "x"}})
;=> :clojure.spec.alpha/invalid

(s/conform ::outer {:tag "x"
                    :inner {:tag "x"}})
;=> {:tag "x", :inner {:tag "x"}}

mmer15:10:57

Thank you - I kind of understand. I need to work through some details.

mmer22:10:42

What seems strange is that with the whole conformed model that it is not easier to walk the model. In other words it woul dbe good to be able to apply the equivalent of an xpath to the specs to be able to find associated data and perform link and checks between them

ikitommi19:10:38

Hi. Wrote an suggestion of the spec coercion: https://dev.clojure.org/jira/browse/CLJ-2251

dealy21:10:30

trying to spec a function that takes 2 params, a keyword and a set of string (which can be nil), but my spec always fails when a set is passed to the function, how should it be spec'd

dealy21:10:12

(s/fdef cs! :args (s/cat :mis keyword? :table-names (or nil? (s/coll-of string?)))) is the spec I was using

bfabry21:10:16

you want (s/or (s/coll-of string? :kind set?) nil?) but really you want (s/nilable (s/coll-of string? :kind set?)

mmer22:10:42

What seems strange is that with the whole conformed model that it is not easier to walk the model. In other words it woul dbe good to be able to apply the equivalent of an xpath to the specs to be able to find associated data and perform link and checks between them