重用相同的 let 绑定
Reusing the same let bindings
我正在为 clojure 应用程序重构我的测试套件,并试图弄清楚是否有一种方法可以保存 let 绑定以供重用以最大限度地减少复制代码,因为许多测试需要类似的设置但会相互干扰并要求自己最熟练。理想情况下,我希望它能像这样工作:
(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 绑定时,因为调用影响测试数据库的方式需要在每次测试后重置。这是否意味着我需要一个宏?
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
...)))
...
要在没有宏的情况下执行此操作,您可以这样做:
(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
您可以使用固定装置重新定义跨测试的动态绑定并访问 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"))
我正在为 clojure 应用程序重构我的测试套件,并试图弄清楚是否有一种方法可以保存 let 绑定以供重用以最大限度地减少复制代码,因为许多测试需要类似的设置但会相互干扰并要求自己最熟练。理想情况下,我希望它能像这样工作:
(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 绑定时,因为调用影响测试数据库的方式需要在每次测试后重置。这是否意味着我需要一个宏?
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
...)))
...
要在没有宏的情况下执行此操作,您可以这样做:
(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
您可以使用固定装置重新定义跨测试的动态绑定并访问 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"))