How do You eval? I actually want the default generator because I override it, but for testing i would also like to test the generic one.
with the eval
function?
(s/gen (eval (s/form ::a)))
Hello, I want to introduce clojure spec to validate API endpoints. The parsed response naturally does not have namespaced keywords. How do I go about validating the data? Should I simply use unqualified keys? Where should I keep my spec?
I know it is a very common question of where to put spec but can't find the right answer
I answered these in #beginners - in the future, it's best to put questions in just one channel
Is it not a bad thing to use the eval function?
it's not inherently bad, it's just a tool
Clojure evals all of your expressions after all
I have a simple function and an associated fdef specification, but am not getting an error when calling the function with incorrect arguments. The function should take a map that is a ::customer
specification. Have I misunderstood something?
(defn customer-fullname
"Return customer full name from customer details"
[customer-details]
(str (::first-name customer-details)
"_"
(::last-name customer-details)))
(spec/fdef customer-fullname
:args (spec/cat :customer ::customer)
:ret string?
:fn #(= (:ret %)
(str (::first-name :args) " " (::last-name :args))))
(spec/def ::first-name string?)
(spec/def ::last-name string?)
(spec/def ::email-address
(spec/and string?
#(re-matches #"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$" %)))
(spec/def ::customer
(spec/keys
:req [::first-name ::last-name ::email-address]))
I would have expected a call to the customer-fullname
to fail when the wrong kind of arguments are passed
(customer-fullname "customer")
The ::customer
spec works with spec/valid?
and spec/assert
when I use them with :pre
and :post
conditions in a function definition, but seem to be missing something when using spec/fdef
.
Ah, I have now learned about instrumenting the fdef
specifications, and now it works, well fails when I expect it too...
(spec-test/instrument `customer-fullname)
I am not clear on if it is valuable to use fdef
without instrumenting them. Some discussions suggest is it but I have not really understood why as yet. I am still not that clear on the :fn
aspect of fdef
so will be on the look out for more examples. I still have a lot to understand about spec.
you can see the specs in (doc customer-fullname)
@jr0cket You can also spec-test/check
them, separate from instrumentation.
^^
those are the main benefits
In particular, instrumentation checks :args
passed in are correct (and ignores :ret
and :fn
). Check is generative and passes in conforming random arguments (per the :args
spec) and then checks :ret
and :fn
are satisfied.
I can see the specs in the docs, yes that is very useful (had forgotten that in my frustration to get the code to fail). Will try out spec-test/check
in the morning, sound promising. Thank you both.