Help develop a small Unit Test macro in Clojure

I have a small unit test macro

(defmacro is [expr value] `(if (= ~expr ~value) 'yes (println "Expected " ~value "In" ~expr "But Evaluated to" ~expr))) 

How to write an error message? Now he gives

 Clojure 1.0.0- 1:1 user=> (is (+ 2 2) 4) user/yes 1:2 user=> (is (+ 2 2) 5) Expected 5 In 4 But Evaluated to 4 

I want to evaluate the expression and say yes, if the estimated value is as expected, print an error with an invaluable expression instead of the value after "B".

+6
functional-programming lisp clojure
source share
2 answers

Original answer

I think this is what you are looking for:

 (defmacro is [expr value] `(if (= ~expr ~value) true (println "Expected " ~value "In" (str (quote ~expr)) "But Evaluated to" ~expr))) 

what (quote ~expr) does, brings the s-expression represented by expr to your "template" but does not allow it to be evaluated, and then applying str to an unvalued s-expression, it turns it into a string to concatenate with other strings error messages. So,

 user=> (is (+ 2 2) 5) Expected 5 In (+ 2 2) But Evaluated to 4 

creates the desired behavior.

Instead of using 'yes to report success, you can simply use true as a report to test success by specifying:

 user=> (is (+ 2 2) 4) true 

and avoid the problem of returning 'yes as a qualified character. If for some reason you need a character, you can make a keyword:

 (defmacro is [expr value] `(if (= ~expr ~value) :yes (println "Expected " ~value "In" (str (quote ~expr)) "But Evaluated to" ~expr))) user=> (is (+ 2 2) 4) :yes 



The answer to the question asked in the comments

You asked in the comments:

I am sorry that I should have been more clear in my question. What is the difference between a symbol and a keyword in this case?

Consider your initial definition (corrected to make the mistake you wanted):

 (defmacro is [expr value] `(if (= ~expr ~value) 'yes (println "Expected " ~value "In" (str (quote ~expr)) "But Evaluated to" ~expr))) 

I assume that you want 'yes think that you can use to test against 'yes in other contexts (often such tests are tested in introductory lisp texts). But 'yes used in the definition of the macro, it returns a qualified character when passing the test:

 user=> (is (+ 2 2) 4) user/yes 

Now this is not what you would like. Imagine you said this:

 user=> (= 'yes (is (+ 2 2) 4)) false 

To get a true answer, you should say this (using a quote from the syntax):

 user=> (= `yes (is (+ 2 2) 4)) true 

If you have defined your macro to return :yes , you will get a returned checkback without the need to parse the object you use to check:

 user=> (= :yes (is (+ 2 2) 4)) true 

But this is all superfluous, because you are really interested in whether (+ 2 2) 4 returns, i.e. whether your statement is true or false , and not 'yes is equal to `yes or ' yes ; you can just have it return ; you can just have it return true` and avoid this verification step (in the real world).

In any case, to understand what qualified characters are, you need to read the docs in the clojure reader and this SO answer explaining the characters and character characters in clojure .

+11
source share

You have a problem with macro "Is". Ask the "Is" macro to return a list that contains something like this: ("Request form for the actual response to the answer") or (: refusal to answer the actual answer). You probably have a DefTest macro to aggregate your claims. This is where you should answer your question.

0
source share

All Articles