重用相同的let绑定

时间:2018-03-08 12:06:41

标签: clojure let

我正在为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绑定时,因为调用会以每次测试后需要重置的方式影响测试数据库。这是否意味着我需要一个宏?

3 个答案:

答案 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"))