Given some function specs we would like to know if there are bugs in a function definition associated with invalid function calls.
(s/fdef foo :args (s/cat :x number? :y number?) :ret string?)
(s/fdef bar :args (s/cat :z coll?) :ret number?)
(defn baz []
(let [a (foo 1 2)]
b (bar a)]
b))
In this specific example, we would like to check that a
(the value returned from the call to foo) will always satisfy the :arg spec for bar
.
Stated another way: we need to check that the string?
generator produces values which satisfies the coll?
predicate.
We can do that by generating values and testing them using s/exercise
and s/valid?
.
We can also cache the output in case we come across this combination again.
Additionally, we can keep examples of values which don't validate to improve error messages with a concrete example.
- What about transitive stuff? Are specs insufficient to catch case where a function's input type relates to it's output type.
- Specs are typically defined/available after function is declared. That means analysis would need to be a separate sweep.