diff --git a/README.md b/README.md index 9ebf0f1..81d8e39 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Like all things in life, defn-spec has benefits and tradeoffs: * defn-spec uses your `:ret` spec as-is, but constructs an `:args` spec for you based on the function's argument names and the 'spec hints' that you provide. * defn-spec should preserve all metadata, docstrings, and type hints in the same way that Clojure's `defn` does. If you spot anything that isn't being retained, this is a bug, let me know! * If you use the `ds/defn` macro, but don't define any 'spec hints' for the arguments or return value then no `fdef` spec is defined. -* When expanding the `ds/defn` macro, the `fdef` is defined immediately after the `clojure.core/defn`. If you declare fdefs after this point, they will overwrite the defn-spec `fdef`. You cannot merge 'spec hints' defined on a function and other spec definitions in a standalone `fdef`. +* When expanding the `ds/defn` macro, the `fdef` is defined immediately before the `clojure.core/defn`. If you declare fdefs after this point, they will overwrite the defn-spec `fdef`. You cannot merge 'spec hints' defined on a function and other spec definitions in a standalone `fdef`. * Unlike schema, defn-spec doesn't control when/if function specs are checked. I recommend using [orchestra](https://github.com/jeaye/orchestra) in development to instrument the `:args`, `:fn`, and `:ret` specs for your `fdef`'s. ## Limitations diff --git a/test/net/danielcompton/defn_spec/alpha_test.clj b/test/net/danielcompton/defn_spec/alpha_test.clj index bb2f1fd..ebf994c 100644 --- a/test/net/danielcompton/defn_spec/alpha_test.clj +++ b/test/net/danielcompton/defn_spec/alpha_test.clj @@ -1,5 +1,4 @@ (ns net.danielcompton.defn-spec.alpha-test - (:refer-clojure :exclude [defn]) (:require [clojure.test :refer :all] [net.danielcompton.defn-spec.alpha :as ds] [orchestra.spec.test :as st] @@ -12,6 +11,9 @@ (st/instrument) (f))) +(defn get-spec [p] + (get @@#'clojure.spec.alpha/registry-ref p)) + (s/def ::int int?) (ds/defn arg-1-fn [x :- int?] @@ -59,6 +61,17 @@ (is (thrown? ExceptionInfo (args-ret-broken 5)))) +(deftest spec-forms-test + (is (= (s/describe (get-spec `args-ret)) + '(fspec :args (cat :x ::int) :ret int? :fn nil))) + + ;; TODO: shouldn't define any :args spec if none is provided, #1 + #_(is (= (s/describe (get-spec `ret-spec)) + '(fspec :args nil :ret ::int :fn nil))) + + (is (= (s/describe (get-spec `arg-2)) + '(fspec :args (cat :x int? :y any?) :ret any? :fn nil)))) + (ds/defn multi-arity ([] 0) @@ -127,8 +140,30 @@ ; (keys-destructuring-named {:int 5 :foo 5})))) ; ) + +(clojure.core/defn standard-defn [x] + nil) + +(ds/defn no-spec-ds-defn [x] + nil) + +(ds/defn only-arg [x :- ::int] + x) + +(ds/defn only-ret :- ::int [x] + x) + +(deftest partial-spec + (testing "standard defn's don't register specs" + (is (nil? (get-spec `standard-defn)))) + + (testing "if no spec hints are provided, no function spec is defined" + ; TODO: broken, see #1 + #_ (is (nil? (s/describe (get-spec `no-spec-ds-defn)))))) + (comment (s/describe (get @@#'clojure.spec.alpha/registry-ref `arg-1-spec)) + )