This post raises the subject discussed here on clojurians
The issue is that would like to have a version of is
which causes the current test to abort, but allows the next test (next test defined by deftest
) to continue.
Here is a real example from one of my projects.
(deftest t-plus-associative
;; check associativity
(doseq [p1 polynomials
p2 polynomials
p3 polynomials]
(is (= (sut/+ (sut/+ p1 p2) p3)
(sut/+ p1 (sut/+ p2 p3)))
(format "Discovered non-associative input for poly-plus\np1=%s\np2=%sp3=%s"
p1 p2 p3))))
The problem with this test is that if the sut/poly-plus
function itself raises an exception, then each is
simply fails, registers the failure, and the next iteration of the doseq
loop continues. I would rather that such an error would cause t-plus-associative
to abort, and the next test (defined by another deftest
to run.
I have fixed this in my project by writing my own version of is
which simply re-throws the exception after registering the failure. I’ve inserted the expression (throw t#)
(defmacro util-try-expr
"modified copy of clojure.test/try-expr"
[msg form]
`(try ~(assert-expr msg form)
(catch Throwable t#
(do-report {:type :error, :message ~msg,
:expected '~form, :actual t#})
;; Now, re-throw the same exception, so the testing framework
;; will abort the current test, considering it a failure.
(throw t#))))
(defmacro is
"Drop-in replacement of clojure.test/il which aborts the current
test if the expression is found to be false."
([form] `(is ~form nil))
([form msg] `(util-try-expr ~msg ~form)))
I think it would be useful to have an alternate to is
which allows a test to fail and finish, rather than explicitly forcing the failing test to continue.