Fork me on GitHub

I've been reminding myself how to use spec and one thing I can't remember is how to get better errors from this sort of thing?

(defn load-order [order-book {:keys [side id] :as order}]
  {:pre [(s/valid? :order/order order)]}
  (assoc-in order-book [side id] order))
Which does give me this:
Execution error (AssertionError) at (market.clj:23).
Assert failed: (is (s/valid? :order/order order))
But considering it's a spec, I was expecting a little more? I've hacked it a bit by wrapping it in an is, which gives me:
FAIL in () (market.clj:2)
expected: (s/valid? :order/order order)
  actual: (not
            {:price 1,
             :size 425.0,
             :side :sell,
             :id 10229,
             :good-kw :inventory}))
But I'm sure there's a better way?


Unfortunately, :pre doesn’t really understand specs so can only assert that a non-truthy value occurred. Three options spring to mind… You could use s/assert outside of your precondition, and enable checking. If you use fdef to specify your :args and turn on instrumentation, you’ll get an error with an explanation. Alternatively, test your specified function and don't call it with the wrong input. Validate data at the boundary (this one might be a little idealistic).


It might be worth asking over in #clojure-spec too?


Thanks 😃