Help with strange test output when deftest used inside a macro

61 views
Skip to first unread message

Matt Grimm

unread,
Oct 9, 2017, 4:40:20 PM10/9/17
to Clojure
Hello,

I'm generating deftest's using a helper macro that takes a variety of test parameters and though the tests function correctly, the output of a failed test is not exactly right. The expect value is shown as the un-evaluated test form, and the actual value is shown as the result of evaluating the test form. I realize 'is' is a macro itself, but I'm not quite sure how to expand or escape the guts of my macro to make the output match that of a normal test.

Whereas a normal test failure looks like this (some output elided):

user=> (deftest normal-test
 
#_=>   (is (= [0 1 5] (range 3))))
#'user/normal-test
user
=> (run-tests)

FAIL in (normal-test)

expected
: [0 1 5]
  actual
: ((0 1 2))

A failure for a deftest defined within a macro comes out like this:

user=> (defmacro defnesttest [v]
  #_=>   `(deftest nested-test
  #_=>      (is (= [0 1 5] ~v))))
#'user/defnesttest
user=> (defnesttest (range 3))
#'user/nested-test
user=> (run-tests)

FAIL in (nested-test)

expected: (clojure.core/= [0 1 5] (range 3))
  actual: false

Thanks for any insight,
m.

Timothy Baldridge

unread,
Oct 9, 2017, 5:32:29 PM10/9/17
to clo...@googlegroups.com
The problem isn't the macro, it's your use of syntax quoting. `(= x y) gets expanded at read-time into `(clojure.core/= x y)`. Not much you can do about that. Although I'd suggest perhaps changing your code a bit to not require macros. 

deftest mostly just creates a defn with some extra metadata and the like. One option would be to use a dynamic var to setup your config information. Or better yet have the test itself read the config data the way your normal app would. This not only exercises the same config codepaths, but it also keeps the code quite functional. 

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
“One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.”
(Robert Firth)

Gary Verhaegen

unread,
Oct 10, 2017, 5:10:37 AM10/10/17
to clo...@googlegroups.com
is is looking for specific patterns and, if it can't find a known one, defaults to assuming its argument is a random predicate and prints that.

So what's happening here is the syntax quote expands (resolves) = to clojure.core/= and thus it doesn't match the pattern for = anymore.

So you'd need for = to not be expanded and stay as exactly the = symbol after macroexpansion. There are various ways to achieve that, but I can't think of a generic, elegant one. In the trivial example you posted you can just replace = with ~'=, I think, though that might not be so easy on more complex macros.

You can also take a look at the assert-expr and report multimethods in clojure.test.

For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.

Matt Grimm

unread,
Oct 10, 2017, 10:10:32 AM10/10/17
to Clojure
Excellent, thanks! The actual macro is indeed a little more complicated, but the test assertions are limited to (is (= ...)), so replacing = with ~'= works perfectly.
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
“One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.”
(Robert Firth)
Reply all
Reply to author
Forward
0 new messages