Nut*_*tim 10 unit-testing clojure generative-testing
无论如何在广义测试套件中包含clojure.spec'd函数?我知道我们可以注册规格和直接规范功能.
(ns foo
(:require [clojure.spec :as s]
[clojure.spec.test :as stest]))
(defn average [list-sum list-count]
(/ list-sum list-count))
(s/fdef average
:args (s/and (s/cat :list-sum float? :list-count integer?)
#(not (zero? (:list-count %))))
:ret number?)
Run Code Online (Sandbox Code Playgroud)
后来,如果我想针对该spec'd函数运行生成测试,我可以使用stest/check.
=> (stest/check `average)
({:spec #object[clojure.spec$fspec_impl$reify__14282 0x68e9f37c "clojure.spec$fspec_impl$reify__14282@68e9f37c"], :clojure.spec.test.check/ret {:result true, :num-tests 1000, :seed 1479587517232}, :sym edgar.core.analysis.lagging/average})
Run Code Online (Sandbox Code Playgroud)
但是i)无论如何都要在我的通用测试套件中包含这些测试运行?我正在考虑test.check所具有的那种clojure.test集成.我能看到的最接近的东西ii)是(见这里)函数.但这似乎只是让我们开始检查repl.不是我想要的.另外,iii)是否注册了功能规格?stest/instrument
(defspec foo-test
100
;; NOT this
#_(prop/for-all [v ...]
(= v ...))
;; but THIS
(stest/some-unknown-spec-fn foo))
Run Code Online (Sandbox Code Playgroud)
好的,解决了这个.事实证明,没有开箱即用的解决方案.但是一些关于clojure-spec slack channel的人已经defspec-test为clojure.spec.test和clojure.test提供了一个解决方案.
所以考虑到问题中的代码.您可以A)定义defspec-test获取测试名称的宏和规范函数列表.然后,您可以B)在您的测试套件中使用它.
谢谢Clojure社区!! 希望这样的实用功能使其成为核心库.
一个)
(ns foo.test
(:require [clojure.test :as t]
[clojure.string :as str]))
(defmacro defspec-test
([name sym-or-syms] `(defspec-test ~name ~sym-or-syms nil))
([name sym-or-syms opts]
(when t/*load-tests*
`(def ~(vary-meta name assoc
:test `(fn []
(let [check-results# (clojure.spec.test/check ~sym-or-syms ~opts)
checks-passed?# (every? nil? (map :failure check-results#))]
(if checks-passed?#
(t/do-report {:type :pass
:message (str "Generative tests pass for "
(str/join ", " (map :sym check-results#)))})
(doseq [failed-check# (filter :failure check-results#)
:let [r# (clojure.spec.test/abbrev-result failed-check#)
failure# (:failure r#)]]
(t/do-report
{:type :fail
:message (with-out-str (clojure.spec/explain-out failure#))
:expected (->> r# :spec rest (apply hash-map) :ret)
:actual (if (instance? Throwable failure#)
failure#
(:clojure.spec.test/val failure#))})))
checks-passed?#)))
(fn [] (t/test-var (var ~name)))))))
Run Code Online (Sandbox Code Playgroud)
B)
(ns foo-test
(:require [foo.test :refer [defspec-test]]
[foo]))
(defspec-test test-average [foo/average])
Run Code Online (Sandbox Code Playgroud)