I see in the doc for clojure.test I can use (is ...) to specify an expression which I expect to be true, and presumably if it fails to be true, the values of the arguments of the expression will be printed.
However if I expect the value to be false what should I do. I could try (is (not (> a b)),
but when it fails, it prints (not (not true)) rather than (not (> 3 4)).
E.g.,
(deftest t-nullable
(let [a 1 b 2]
(is (> a b))
(is (not (> b a)))))
(run-tests 'clojure-rte.core-test)
FAIL in (t-nullable) (form-init4386036104585295471.clj:33)
expected: (> a b)
actual: (not (> 1 2))
FAIL in (t-nullable) (form-init4386036104585295471.clj:34)
expected: (not (> b a))
actual: (not (not true))
The fact that the function’s arguments are printed is a testimony for the power of macros. The macro, is examines the operands at the call site, and writes appropriate error messages which are a function of the text the user wrote, not just as a function of the run-time values.
I wrote a package for common lisp which is somewhat similar to clojure.test. I had assert-true and assert-false for this reason. assert-false as does assert-true looks at its argument which is expected to be an atom or a list of the form (function arg1 arg2 ....), and generates code which will print the values of arg1 arg2 in case the assertion fails and is careful to avoid multiple evaluations. I suppose is does the same thing, and is-not could also, but is simply not implemented.
In my opinion that goes in the wrong direction. Many languages lacking macros come up with a huge set of predicates for testing different things. assert-<assert->assert-containsassert-equal-case-independent, assert-blah. I think all you need for asserting the return value is to assert true and false. And you also need (apparently as clojure.test already has) a way to assert exceptions or lack thereof.