clojure.spec.alpha
позволяет использовать неразрешимые спецификации при определении новой:
(s/def :foo/bar (s/or :nope :foo/foo))
Здесь :foo/foo
не может быть разрешено, поэтому использование :foo/bar
вызовет исключение при использовании:
(s/valid? :foo/bar 42)
;; Exception Unable to resolve spec: :foo/foo clojure.spec.alpha/reg-resolve! (alpha.clj:69)
Это то, что происходит в моем коде, когда я делаю опечатки, такие как :my-ns/my-spec
вместо ::my-ns/my-spec
. Я хотел бы поймать их с помощью модульных тестов.
Погружение в clojure.spec.alpha
исходный код Я обнаружил, что могу получить все характеристики с помощью (keys (s/registry))
, поэтому мой тест выглядит следующим образом:
(ns my-ns.spec-test
(:require [clojure.test :refer :all]
[clojure.spec.alpha :as s]
;; :require all the relevant namespaces to populate the
;; global spec registry.
[my-ns.spec1]
[my-ns.spec2]))
(deftest resolvable-specs
(doseq [spec (keys (s/registry))]
(is (resolvable? spec))))
;; ^^^^^^^^^^^ placeholder; that’s the function I want
К сожалению, нет такой вещи, как s/resolvable?
в clojure.spec.alpha
. Единственное решение, которое я нашел до сих пор, — это вызвать (s/valid? spec 42)
и предположить, что отсутствие возбуждения исключения означает, что оно разрешимо, но не проверяет все ветки:
(s/def :int/int int?)
(s/def :bool/bool bool?)
(s/def :my/spec (s/or :int :int/int
:other (s/or :bool bool/bool
:nope :idont/exist)))
(s/valid? :my/spec 1) ; <- matches the :int branch
;; => true
(s/valid? :my/spec :foo)
;; Exception Unable to resolve spec: :idont/exist clojure.spec.alpha/reg-resolve! (alpha.clj:69)
Я проверил трассировку стека исключений, а также исходный код, чтобы увидеть, могу ли я найти какую-либо функцию для полного разрешения спецификации без использования тестового значения, такого как 42
или :foo
выше, но не смог найти ни одной.
Есть ли способ проверить, что для данной спецификации все спецификации, на которые она ссылается во всех ее ветвях, действительно существуют?