You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: content/guides/spec.adoc
+39-35Lines changed: 39 additions & 35 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,26 +11,28 @@ toc::[]
11
11
12
12
== Getting started
13
13
14
-
The <<xref/../../../about/spec#,spec>> library specifies the structure of data, validates or destructures it, and can generate data based on the spec. The https://clojure.github.io/clojure/branch-master/clojure.spec-api.html[clojure.spec] namespace is included in the Clojure core distribution, so no extra library is required to use it. You will need to declare a dependency on the latest alpha version of Clojure (or higher) however:
14
+
The <<xref/../../../about/spec#,spec>> library specifies the structure of data, validates or destructures it, and can generate data based on the spec.
15
+
16
+
To use spec, declare a dependency on the latest alpha version of Clojure (or higher):
15
17
16
18
[source, clojure]
17
19
----
18
-
[org.clojure/clojure "1.9.0-alpha15"]
20
+
[org.clojure/clojure "1.9.0-alpha16"]
19
21
----
20
22
21
-
To start working with spec, require the `clojure.spec` namespace at the REPL:
23
+
To start working with spec, require the `clojure.spec.alpha` namespace at the REPL:
22
24
23
25
[source,clojure]
24
26
----
25
-
(require '[clojure.spec :as s])
27
+
(require '[clojure.spec.alpha :as s])
26
28
----
27
29
28
30
Or include spec in your namespace:
29
31
30
32
[source,clojure]
31
33
----
32
34
(ns my.ns
33
-
(:require [clojure.spec :as s]))
35
+
(:require [clojure.spec.alpha :as s]))
34
36
----
35
37
36
38
== Predicates
@@ -45,9 +47,9 @@ Any existing Clojure function that takes a single argument and returns a truthy
45
47
;;=> 1000
46
48
----
47
49
48
-
The `conform` function takes something that can be a spec and a data value. Here we are passing a predicate which is implicitly converted into a spec. The return value is "conformed". Here, the conformed value is the same as the original value - we'll see later where that starts to deviate. If the value does not conform to the spec, the special value `:clojure.spec/invalid` is returned.
50
+
The `conform` function takes something that can be a spec and a data value. Here we are passing a predicate which is implicitly converted into a spec. The return value is "conformed". Here, the conformed value is the same as the original value - we'll see later where that starts to deviate. If the value does not conform to the spec, the special value `:clojure.spec.alpha/invalid` is returned.
49
51
50
-
If you don't want to use the conformed value or check for `:clojure.spec/invalid`, the helper https://clojure.github.io/clojure/branch-master/clojure.spec-api.html#clojure.spec/valid?[`valid?`] can be used instead to return a boolean.
52
+
If you don't want to use the conformed value or check for `:clojure.spec.alpha/invalid`, the helper https://clojure.github.io/clojure/branch-master/clojure.spec-api.html#clojure.spec/valid?[`valid?`] can be used instead to return a boolean.
51
53
52
54
[source,clojure]
53
55
----
@@ -185,7 +187,7 @@ In addition to `explain`, you can use https://clojure.github.io/clojure/branch-m
185
187
[source,clojure]
186
188
----
187
189
(s/explain-data ::name-or-id :foo)
188
-
;;=> #:clojure.spec{
190
+
;;=> #:clojure.spec.alpha{
189
191
;; :problems ({:path [:name],
190
192
;; :pred string?,
191
193
;; :val :foo,
@@ -200,7 +202,7 @@ In addition to `explain`, you can use https://clojure.github.io/clojure/branch-m
200
202
201
203
[NOTE]
202
204
====
203
-
This result also demonstrates the new namespace map literal syntax added in 1.9.0-alpha8. Maps may be prefixed with `#:` or `#::` (for autoresolve) to specify a default namespace for all keys in the map. In this example, this is equivalent to `{:clojure.spec/problems ...}`
205
+
This result also demonstrates the new namespace map literal syntax added in 1.9.0-alpha8. Maps may be prefixed with `#:` or `#::` (for autoresolve) to specify a default namespace for all keys in the map. In this example, this is equivalent to `{:clojure.spec.alpha/problems ...}`
204
206
====
205
207
206
208
== Entity Maps
@@ -651,9 +653,9 @@ Another option is to use `s/assert` within your code to assert that a value sati
A deeper level of integration is to call conform and use the return value to destructure the input. This will be particularly useful for complex inputs with alternate options.
@@ -765,7 +767,7 @@ The Clojure macroexpander will look for and conform :args specs registered for m
765
767
(declare 100)
766
768
;; ExceptionInfo: Call to clojure.core/declare did not conform to spec:
Because macros are always checked during macro expansion, you do not need to call instrument for macro specs.
@@ -877,11 +879,11 @@ In Maven, declare your dependency as a test scope dependency:
877
879
</project>
878
880
----
879
881
880
-
In your code you also need to include the `clojure.spec.gen` namespace:
882
+
In your code you also need to include the `clojure.spec.gen.alpha` namespace:
881
883
882
884
[source,clojure]
883
885
----
884
-
(require '[clojure.spec.gen :as gen])
886
+
(require '[clojure.spec.gen.alpha :as gen])
885
887
----
886
888
887
889
=== Sampling Generators
@@ -1026,7 +1028,7 @@ Building your own generator gives you the freedom to be either narrower and/or b
1026
1028
There are three ways to build up custom generators - in decreasing order of preference:
1027
1029
1028
1030
. Let spec create a generator based on a predicate/spec
1029
-
. Create your own generator from the tools in clojure.spec.gen
1031
+
. Create your own generator from the tools in clojure.spec.gen.alpha
1030
1032
. Use test.check or other test.check compatible libraries (like https://github.com/gfredericks/test.chuck[test.chuck])
1031
1033
1032
1034
[WARNING]
@@ -1067,11 +1069,11 @@ Note that `with-gen` (and other places that take a custom generator) take a no-a
1067
1069
1068
1070
One downside to this approach is we are missing what property testing is really good at: automatically generating data across a wide search space to find unexpected problems.
1069
1071
1070
-
The clojure.spec.gen namespace has a number of functions for generator "primitives" as well as "combinators" for combining them into more complicated generators.
1072
+
The clojure.spec.gen.alpha namespace has a number of functions for generator "primitives" as well as "combinators" for combining them into more complicated generators.
1071
1073
1072
1074
[NOTE]
1073
1075
====
1074
-
Nearly all of the functions in the clojure.spec.gen namespace are merely wrappers that dynamically load functions of the same name in test.check. You should refer to the documentation for https://clojure.github.io/test.check/[test.check] for more details on how all of the clojure.spec.gen generator functions work.
1076
+
Nearly all of the functions in the clojure.spec.gen.alpha namespace are merely wrappers that dynamically load functions of the same name in test.check. You should refer to the documentation for https://clojure.github.io/test.check/[test.check] for more details on how all of the clojure.spec.gen.alpha generator functions work.
1075
1077
====
1076
1078
1077
1079
In this case we want our keyword to have open names but fixed namespaces. There are many ways to accomplish this but one of the simplest is to use https://clojure.github.io/clojure/branch-master/clojure.spec-api.html#clojure.spec.gen/fmap[`fmap`] to build up a keyword based on generated strings:
To learn more about generators, read the test.check https://clojure.github.io/test.check/intro.html[tutorial] or https://clojure.github.io/test.check/generator-examples.html[examples]. Do keep in mind that while clojure.spec.gen is a large subset of clojure.test.check.generators, not everything is included.
1156
+
To learn more about generators, read the test.check https://clojure.github.io/test.check/intro.html[tutorial] or https://clojure.github.io/test.check/generator-examples.html[examples]. Do keep in mind that while clojure.spec.gen.alpha is a large subset of clojure.test.check.generators, not everything is included.
1155
1157
1156
1158
== Instrumentation and Testing
1157
1159
1158
-
spec provides a set of development and testing functionality in the `clojure.spec.test` namespace, which we can include with:
1160
+
spec provides a set of development and testing functionality in the `clojure.spec.test.alpha` namespace, which we can include with:
1159
1161
1160
1162
[source,clojure]
1161
1163
----
1162
-
(require '[clojure.spec.test :as stest])
1164
+
(require '[clojure.spec.test.alpha :as stest])
1163
1165
----
1164
1166
1165
1167
=== Instrumentation
@@ -1178,9 +1180,11 @@ Instrument takes a fully-qualified symbol so we use `pass:[`]` here to resolve i
1178
1180
(ranged-rand 8 5)
1179
1181
CompilerException clojure.lang.ExceptionInfo: Call to #'spec.examples.guide/ranged-rand did not conform to spec:
The error fails in the second args predicate that checks `(< start end)`. Note that the `:ret` and `:fn` specs are not checked with instrumentation as validating the implementation should occur at testing time.
@@ -1189,16 +1193,16 @@ Instrumentation can be turned off using the complementary function `unstrument`.
1189
1193
1190
1194
=== Testing
1191
1195
1192
-
We mentioned earlier that `clojure.spec.test` provides tools for automatically testing functions. When functions have specs, we can use https://clojure.github.io/clojure/branch-master/clojure.spec-api.html#clojure.spec.test/check[`check`], to automatically generate tests that check the function using the specs.
1196
+
We mentioned earlier that `clojure.spec.test.alpha` provides tools for automatically testing functions. When functions have specs, we can use https://clojure.github.io/clojure/branch-master/clojure.spec-api.html#clojure.spec.test/check[`check`], to automatically generate tests that check the function using the specs.
1193
1197
1194
1198
`check` will generate arguments based on the `:args` spec for a function, invoke the function, and check that the `:ret` and `:fn` specs were satisfied.
`check` has reported an error in the `:fn` spec. We can see the arguments passed were -3 and 0 and the return value was -5, which is out of the expected range.
0 commit comments