Welcome! Please see the About page for a little more info on how this works.

0 votes
ago in ClojureScript by
edited ago by

Hi! Thanks for ClojureScript - we're using it more and more and it's amazing.

Something has been bothering me about testing in the repl, and I figured out what it is today.

Check this out:

harold@straylight:~/src/cljs-test-exception$ cat deps.edn 
{:deps {org.clojure/clojurescript {:mvn/version "1.11.132"}}}
harold@straylight:~/src/cljs-test-exception$ clj -M --main cljs.main --repl
ClojureScript 1.11.132
cljs.user=> (require '[cljs.test :refer [deftest]])
nil
cljs.user=> (deftest foo [] (throw (js/Error. "oops!")))
#'cljs.user/foo
cljs.user=> (foo)

ERROR in (foo) (Error:NaN:NaN)
Uncaught exception, not in assertion.
expected: nil
  actual: #object[Error Error: oops!]
nil

When I have a test that's calling into buggy code and an exception is thrown, I don't get the stack trace.

Compare this with clojure.test, which has more helpful output:

user> (require '[clojure.test :refer [deftest]])
nil
user> (deftest foo [] (throw (Exception. "Ooops!")))
#'user/foo
user> (foo)

ERROR in (foo) (NO_SOURCE_FILE:13)
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.Exception: Ooops!
 at user$fn__10841.invokeStatic (NO_SOURCE_FILE:13)
    user/fn (NO_SOURCE_FILE:13)
    clojure.test$test_var$fn__9894.invoke (test.clj:717)
    clojure.test$test_var.invokeStatic (test.clj:717)
    clojure.test$test_var.invoke (test.clj:708)
    user$foo.invokeStatic (NO_SOURCE_FILE:13)
    user$foo.invoke (NO_SOURCE_FILE:13)
    user$eval10844.invokeStatic (NO_SOURCE_FILE:15)
    user$eval10844.invoke (NO_SOURCE_FILE:15)
    clojure.lang.Compiler.eval (Compiler.java:7700)
    nrepl.middleware.interruptible_eval$evaluator$run__1435$fn__1446.invoke (interruptible_eval.clj:106)
    nrepl.middleware.interruptible_eval$evaluator$run__1435.invoke (interruptible_eval.clj:101)
    nrepl.middleware.session$session_exec$session_loop__1519.invoke (session.clj:230)
    nrepl.SessionThread.run (SessionThread.java:21)
nil

Maybe cljs.test could be improved to also include this useful information. I believe it would help with repl test/debugging workflows.

Thanks so much for your time and consideration.


Edit:

Eugene makes an interesting point in the comments.

There is a similar difference in exception/error printing:

In cljs:

harold@straylight:~/src/cljs-test-exception$ clj -M --main cljs.main --repl
ClojureScript 1.11.132
cljs.user=> (ex-info "hi" {})
#error {:message "hi", :data {}}
cljs.user=> 

In clj:

user> (ex-info "hi" {})
#error {
 :cause "hi"
 :data {}
 :via
 [{:type clojure.lang.ExceptionInfo
   :message "hi"
   :data {}
   :at [user$eval8563 invokeStatic "NO_SOURCE_FILE" 11]}]
 :trace
 [[user$eval8563 invokeStatic "NO_SOURCE_FILE" 11]
  [user$eval8563 invoke "NO_SOURCE_FILE" 11]
  [clojure.lang.Compiler eval "Compiler.java" 7700]
  [nrepl.middleware.interruptible_eval$evaluator$run__1435$fn__1446 invoke "interruptible_eval.clj" 106]
  [nrepl.middleware.interruptible_eval$evaluator$run__1435 invoke "interruptible_eval.clj" 101]
  [nrepl.middleware.session$session_exec$session_loop__1519 invoke "session.clj" 230]
  [nrepl.SessionThread run "SessionThread.java" 21]]}

However, in the testing case, clojure.test explicitly prints the stack trace:

https://github.com/clojure/clojure/blob/fb22fd778a272b034684a4ee94509552b46ee8a9/src/clj/clojure/test.clj#L394

While cljs does not:

https://github.com/clojure/clojurescript/blob/d701b452b3f0b09f13191094bff9d5763a449191/src/main/cljs/cljs/test.cljs#L338-L344


It does still seem like the Error object is being swallowed, I don't see a way to gain access to it after running the test that threw.

ago by
The exception is definitely not swallowed - you can see it right there. But the stack trace is not shown, and I'd guess it's just how the REPL prints exception values. Try to evaluate something like `(ex-info "hi" {})` in a CLJ and a CLJS REPLs - there will also be a similar difference. And the exception, if stored, can still be expected, its stacktrace can still be retrieved.
ago by
Thanks Eugene, great thoughts as usual. I amended my question with additional information based on your ideas.

Please log in or register to answer this question.

...