Other languages have property based testing libraries, like Haskell QuickCheck. How does Clojure spec differ from such libraries? Or is it just a property based testing framework for Clojure?
-
2Also see "what is spec" https://stackoverflow.com/a/38518300/1327651 – nha Oct 19 '17 at 13:26
1 Answers
Clojure's analog for QuickCheck would be test.check. Clojure.spec relies on test.check for generative testing, but spec can be used for much more than testing.
Test.check provides tools for generative and property-based testing. Clojure.spec allows you to write specifications for data, and can create generators from those specs automatically. Using test.check alone, you'd need to create non-trivial generators by hand. With clojure.spec, generators can (with some exceptions) be derived from your spec.
(s/def ::my-spec string?) ;; a trivial spec, any string will do
(sgen/sample (s/gen ::my-spec)) ;; create a generator from spec and get samples
;;=> ("" "P" "B" "" "qV" "im4P" "Zf" "" "rL24" "wAV7z")
These generators can be used to generate input data for functions of which you want to test properties. You can write property-based tests using just test.check, and you can also write some property-based tests for functions using clojure.spec. Here's an example of a function that takes a string and returns the "doubled" string:
(defn doubler [s] (str s s))
(s/fdef doubler
:args (s/cat :s string?)
:ret string?
:fn (fn [{:keys [args ret]}]
(= (* 2 (count (:s args))) (count ret))))
(stest/check `doubler)
The s/fdef
spec defines the properties we want from our function: it takes one string, returns a string, and the returned string should be twice as long as the input. We use check
to ensure these properties hold for a bunch of randomly generated inputs.

- 15,886
- 1
- 20
- 37
-
What does differentiate spec from [test.check](https://github.com/clojure/test.check) is only its ability to automatically create test generators? Is that also what differentiates spec from QuickCheck? Could you present some examples of spec uses outside testing? – dilvan Oct 19 '17 at 10:59
-
1There's no reason to *compare* clojure.spec with test.check or any other property-based testing library; it has many uses and purposes beyond testing, the core of which is writing *specifications* for data structures. The linked overview does a great job of explaining this, and the linked guide has many examples of spec usage outside testing. – Taylor Wood Oct 19 '17 at 11:49
-
When you say specifications for data structures, do you mean for human consumption? Or is there something a program can do with it (besides testing)? – dilvan Oct 19 '17 at 15:44
-
In the [guide](https://clojure.org/guides/spec), I found examples about specification, testing, explaining test results (spec violations) and generators. In the [what is spec question](https://stackoverflow.com/a/38518300/1327651) I found "Conform" a value which gives you a parsed and destructured version of the value" outside testing. – dilvan Oct 19 '17 at 15:57
-
1Yes, the specs are both human- and machine-readable. For example, a program can use spec to assert some data (maybe user input) conforms to a specification. Building on that, there are libraries like [Expound](https://github.com/bhb/expound) that can render spec problems in a more human-readable format. Then there's [Phrase](https://github.com/alexanderkiel/phrase) which is meant for turning spec problems into end-user-friendly messages. – Taylor Wood Oct 19 '17 at 16:06
-
1In a nutshell, spec goal is to create specifications that can be used for testing and for human consumption (there are tools to make them more human readable). When compared to other tools (QuickCheck, etc), spec is more expressive, allowing descriptions that can be used in place of textual specifications. Did I get it right? – dilvan Oct 20 '17 at 09:43