我正在为clojure应用程序重构我的测试套件,并试图找出是否有办法保存let绑定以便重复使用以最小化复制的代码,因为许多测试需要类似的设置但是相互干扰并要求他们自己的deftest。理想情况下,我希望它有点像这样:
(def let-bindings [bind1 val1 bind2 val2 bind3 val3])
(deftest test-1
(testing "my test"
(let (conj let-bindings [bind4 val4])
...)))
(deftest test-2
(testing "my second test"
(let (conj let-bindings [bind5 val5])
...)))
为了补充说明,我需要在测试中评估val1和val2,而不是在定义let绑定时,因为调用会以每次测试后需要重置的方式影响测试数据库。这是否意味着我需要一个宏?
答案 0 :(得分:1)
let
是一种特殊形式,因此尝试对其进行元编程而不在宏中执行它将无效。也许您应该只定义通用绑定:
(def bind1 val1)
(def bind2 val2)
(def bind3 val3)
(deftest test-1
(testing "my test"
(let [bind4 val4]
;; here bind1...bind4 would be available
...)))
...
修改强>
我想象你可以用宏来做到这一点:
;; notice that the let will be recreated each time so if
;; val1 ... are computational hard consider caching.
(defmacro elet [ bindings & body ]
`(let [bind1 val1 bind2 val2 bind3 val3 ~@bindings]
~@body))
(deftest test-1
(testing "my test"
(elet [bind4 val4]
;; here bind1...bind4 would be available
...)))
...
答案 1 :(得分:0)
要做到这一点,没有宏你可以这样:
(def m {:a 1 :b 2})
(deftest foo []
(println (m :a)))
(foo)
;; prints 1
(let [m (assoc m :c 3)]
(deftest bar
(println (m :c))))
(bar)
;; prints 3
答案 2 :(得分:0)
您可以使用fixture来重新定义跨测试的动态绑定并访问deftest中的值。可以为所有或每个deftest定义一次灯具。
(def ^:dynamic m)
(defn once-fixture
[tests]
(binding [m {:a 1 :b 2}]
(tests)))
(use-fixtures :once once-fixture)
(deftest testing-binding
(is (= (:a m) 1)
"Dynamic binding is working"))