Fork me on GitHub

Is there any way to get more info about why a spec generator is failing? This is the error message:

clojure.lang.ExceptionInfo: Couldn't satisfy such-that predicate after 100 tries. {:pred #object[clojure.spec.alpha$gensub$fn__1876 0x7230d43f "[email protected]"], :gen #clojure.test.check.generators.Generator{:gen #object[clojure.test.check.generators$such_that$fn__45785 0x2ea879fb "[email protected]"]}, :max-tries 100}
Nothing in the stacktrace points to my code. I guess I could go through and individually test all my specs for which failed but in this case the spec is huge and that would be very time consuming.


@kenny not an answer to your direct question, but that particular failure is usually caused by an s/and, where one of the non-initial predicates is not likely to happen by chance


(or all of them together, more accurately)


Right. There's a lot of those 😞


it's a long outstanding issue between spec and test.check; test.check's alphas have a feature in such-that that would let spec report what spec is causing it


but spec doesn't use that feature yet afaik


It doesn't help you now @kenny but when I'm writing specs, I pretty much always have a (comment ..) form with calls to s/exercise for each of my specs, and I make sure they generate as I'm writing them... for exactly this reason.


I have some decent guesses for the ones that fail but the feature @gfredericks mentioned would significantly improve this experience. Then you could get rid of all those comment blocks @seancorfield😉


Any idea if there's a jira issue for this?


I have a lot of Rich Comment Forms in my code 🙂


I find they're a good way to keep notes about my thinking as I develop, as well as containing expressions that produce test data and show usage of functions -- and specs 🙂


what would be the recommend way to do a multi-spec dispatch for some nested map variable ? e.g. let's say that i have this

{:entity/type :user
 {:user/id 1234}}
and i want to multi-spec the :entity/data based on the :entity/type ... this seems pretty tricky ?


because this is not possible, although it's something that i would want:

(s/def :entity/data (s/multi-spec entity-data :entity/type))
(s/def :entity (s/keys :req [:entity/type :entity/data]))


now i could repeat :entity/type as a property of :entity/data again, but that seems redundant


If you really have to, you can use multispec with the dispatch on type. Repeat this for all the different types:

(s/def :your/data any?)

 (s/coll-of (s/or :type (s/tuple #{:entity/type} #{:user})
                  :data (s/tuple #{:entity/data}
            :kind map?)
 {:entity/type :user
  :entity/data :foo})


If you control the design of the data, but i guess you dont, there is probably a better way more in line with clojure.spec


🤔 not sure whether this is brilliant or evil


it works though


how would you redesign the data ? lift the data inside :entity/data into the parent map so that multispec works ?


how would you redesign the data ? lift the data inside :entity/data into the parent map so that multispec works ?


yeah sorry for giving the evil hack 🙂 Changing the data will make it much cleaner. And using multispec for example gives you very nice specific validation errors e.g. when using it with expound


yes thanks a lot, your comment was helpful!


btw, not using a namespaced keyword, so :data instead of :entity/data could also be used as a fix instead of lifting the data inside. You would use s/keys with :req-un instead of :req


actually that makes a lot of sense


qualified keywords allow you to have a mix of "unrelated" keys in a flat map


yes, it is obvious that I was doing this wrong


makes a lot of sense