clojure clojure.spec fdef: writing a spec for a function


Let's say we have the following function:

(defn nat-num-count [nums] (count (remove neg? nums)))

We can write a spec for this function by defining a function spec of the same name:

(clojure.spec/fdef nat-num-count
        :args (s/cat :nums (s/coll-of number?))
        :ret integer?
        :fn #(<= (:ret %) (-> % :args :nums count)))

:args takes a regex spec which describes the sequence of arguments by a keyword label corresponding to the argument name and a corresponding spec. The reason the spec required by :args is a regex spec is to support multiple arities for a function. :ret specifies a spec for the return value of the function.

:fn is a spec which constrains the relationship between the :args and the :ret. It is used as a property when run through test.check. It is called with a single argument: a map with two keys: :args (the conformed arguments to the function) and :ret (the function's conformed return value).