开发者

How do I rebind a var in a Lazytest 'describe' test?

开发者 https://www.devze.com 2023-01-30 18:39 出处:网络
First of all, sor开发者_StackOverflow社区ry if I am screwing up some terminology; I\'m pretty new to Clojure.I am trying to write a very simple test using Lazytest that depends on a var binding.I can

First of all, sor开发者_StackOverflow社区ry if I am screwing up some terminology; I'm pretty new to Clojure. I am trying to write a very simple test using Lazytest that depends on a var binding. I can not seem to rebind a var in the test file and have the code under test use that binding.

Here is the code I am trying to test:

(ns liar-liar.core
  (:gen-class))

(def *input-file-name*)

(defn parse-input
  "Just print return a var for now..."
  []
  *input-file-name*)

(defn -main [& args]
  (binding [*input-file-name* (first args)]
    (println (parse-input))))

And here is the test:

(ns liar-liar.test.core
  (:use lazytest.describe)
  (:use liar-liar.core))

(binding [*input-file-name* "my-input-file"]
  (describe parse-input "Just returns a var"
    (it "returns a var"
      (= "my-input-file" (parse-input)))))

When I try to run this test, I get this error:

java.lang.IllegalStateException: Var liar-liar.core/*input-file-name* is unbound.

Interestingly enough, if I move the binding form:

(ns liar-liar.test.core
  (:use lazytest.describe)
  (:use liar-liar.core))

(describe parse-input "Just returns a var"
  (it "returns a var"
    (binding [*input-file-name* "my-input-file"]
      (= "FAIL" (parse-input)))))

The test works as it should, but the reporting isn't ideal, as it doesn't print the value of the (parse-input) expression (the test passes if I replace "FAIL" with "my-input-file" though):

FAILURE: Namespaces liar-liar.test.core #'liar-liar.core/parse-input Just returns a var returns a var
at liar_liar/test/core.clj line 7
Expression: (binding [*input-file-name* my-input-file] (= FAIL (parse-input)))
Result: false
Local bindings:
{}

Is there some other way I should be going about doing this kind of testing?

Thanks! Dan


I think your expectation of how this should work is reasonable, but I have a feeling the describe and it macros are evaluating *input-file-name* before your binding form has a chance to bind it. I've found in my brief Lazytest explorations that I'm better off sticking with the forms provided by the framework than trying to wrap either of those two macros with let or binding forms.

These kinds of problems seem to be fairly frequent (for me, anyway) when using dynamic binding to "push" arguments to a function. It's much more reliable and understandable to actually pass that argument in, where possible.


As described by Stuart Sierra on the Clojure google group (block quote's not working here):

Both describe and it create functions. That is, they expand out to (fn [] ...). Wrapping binding around the creation of a fn has no effect.

For finer control over where the fn gets created and how failures get reported, you can use do-it and expect.

(describe ... (do-it ... (binding ... (expect ...)))

This will produce the results you're looking for.

http://groups.google.com/group/clojure/browse_thread/thread/d181e4731bdf9beb

Indeed, they did produce the results I was looking for :)

0

精彩评论

暂无评论...
验证码 换一张
取 消