marick / Midje

Midje provides a migration path from clojure.test to a more flexible, readable, abstract, and gracious style of testing
MIT License
1.69k stars 129 forks source link

Pretty print full exception when midje fails at load-time #402

Closed philomates closed 7 years ago

philomates commented 7 years ago

The error messages shown when midje fails to load files at autotest startup only show the exception's message. Hence, useful error information that is in the exception's data (in the case of clojure.lang.ExceptionInfo) or exceptions with nested causing exceptions, is hidden.

Before:

LOAD FAILURE for your-service-test
clojure.lang.ExceptionInfo: Error in component :routes in system com.stuartsierra.component.SystemMap calling #'com.stuartsierra.component/start {:reason :com.stuartsierra.component/component-function-threw-exception, :function #'com.stuartsierra.component/start, :system-key :routes, :component <Routes>, :system #<SystemMap>}, compiling:(your_service_test.clj:8:1)

After:

clojure.lang.ExceptionInfo: Error in component :routes in system com.stuartsierra.component.SystemMap calling #'com.stuartsierra.component/start 

  some-exception-data "foo"
  function: #'com.stuartsierra.component/start
  reason: :com.stuartsierra.component/component-function-threw-exception
  some-more-exception-data "bar"
  details: {:from routes/validate-auth,
            :reason :invalid-routes,
            :routes ("/some/api/endpoint")}
  type: :server-error
                                                      clojure.core/ex-info           core.clj: 4617
                                            util.exceptions/make-exception     exceptions.clj:   42
                                                 util.exceptions/terminate     exceptions.clj:   24
                                                   clojure.core/partial/fn           core.clj: 2522

Also currently the exceptions printed on load failures when doing a (load-facts) from the repl looks like this:

= Namespace midje.t-repl

             clojure.lang.ExceptionInfo: blarg
clojure.lang.Compiler$CompilerException: clojure.lang.ExceptionInfo: blarg {}, compiling:(midje/foo.clj:2:1)

This PR updates it to look like this

= Namespace midje.t-repl
LOAD FAILURE for midje.t-repl
clojure.lang.Compiler$CompilerException: clojure.lang.ExceptionInfo: blarg {}, compiling:(midje/foo.clj:2:1)
             clojure.lang.ExceptionInfo: blarg
                  clojure.core/ex-info    core.clj: 4617
                   midje.foo/eval42156     foo.clj:    2
                                   ...                  
                  clojure.core/load/fn    core.clj: 5893
                     clojure.core/load    core.clj: 5892
                     clojure.core/load    core.clj: 5876
                                   ...                  
rafaeldff commented 7 years ago

It would be cool if users could customize the exception handler.

philomates commented 7 years ago

@rafaeldff regarding https://github.com/marick/Midje/pull/402#issuecomment-327527547 for now I'm just going to create a :pretty-print config flag that is by default set to true, but when set to false defaults to the old way of formatting exceptions (in case anyone doesn't like the change).

I also use the :pretty-print in this PR https://github.com/marick/Midje/pull/404 to turn of pretty printing of expected output

This isn't ideal or very configurable, so I will look into allowing custom exception handlers in the future.

For now I ran into some issues trying to implement that: I tried basing my plugin system on protocols and ran into issues of reloading protocol definitions and trying to use them with old instances (due to how midje reloads code on changes). So I tried to fix how midje reloads changes using clojure.tools.namespaces but ran into more issues. I'm going to keep poking at it, but I want to get this out in the meantime.