clojure-emacs/cider

cider-test-highlight-problems working in wrong buffer

pgroce opened this issue · 11 comments

When running cider-test-run-tests, if a test fails in a part of the code other than the test (e.g., "Uncaught exception, not in assertion"), CIDER tries to highlight the problematic test using the line number information from the exception, which is for a different file. For me, this turns into an error when goto-line tries to go to a nonexistent line in the test.

I'm not sure how you want to fix this. Ideally, you'd want to always highlight the line in the test that's causing the failure; that would probably involve delving further into the trace to find the first line that mentions the test file and passing that information around, eventually using it in cider-test-highlight-problems.

A simpler workaround is not to highlight the test when the file name and the buffer-file-name don't match. This is obviously ugly, but I've implemented this and it seems to work well enough. The changed function and a (disappointingly unclear) diff are in this Gist -- the changes are adding file to nrepl-dbind-response and wrapping the remainder of the function in the following when clause.

@jeffvalk, would you please have a look at this?

@pgroce Do you have the latest cider-nrepl snapshot? This sounds like #648, which was fixed in the middleware.

Yes. I downloaded a new one when I upgraded yesterday. In my main project (which uses Gradle), I went into the lib directory containing the dependency jars and inspected the CIDER jar to ensure that it has the changes in clojure-emacs/cider-nrepl@c6e0389.

To isolate the issue from the idiosyncrasies of my current project, I have created a new Leiningen-based project that reproduces the bug on my system. (The reproduction is slightly different from the one in #648, but that one tickles the bug, too.)

Some extra diagnostics. I modified cider-test-highlight-problem thusly:

  (defun cider-test-highlight-problem (buffer test)
    "Highlight the BUFFER test definition for the non-passing TEST."
    (message "In cider-test-highlight-problem")
    (with-current-buffer (pg/spy buffer)
      (nrepl-dbind-response test (type line message expected actual)
        (pg/spy test)
        (message "Leaving cider-test-highlight-problem"))))

When I ran cider-test-run-tests in core.clj in the above project, I got the following output:

In cider-test-highlight-problem
buffer = core_test.clj
test = (dict (actual . #<RuntimeException java.lang.RuntimeException: foo>) (context . ) (error . java.lang.RuntimeException: foo) (expected . nil) (file . core.clj) (index . 0) (line . 706) (message . Uncaught exception, not in assertion.) (ns . cider-bug-674.core-test) (type . error) (var . a-test))
Leaving cider-test-highlight-problem

(As you can guess, pg/spy is a debug macro that writes <form>=<value> to *Messages* and returns the evaluated value.)

I have no idea where that (line . 706) comes from. For reference, here's the stack trace as reported in the *cider-error* buffer (no filters):

1. Unhandled java.lang.RuntimeException
   foo

                      core.clj:    3  cider-bug-674.core/throw-error
                 core_test.clj:    7  cider-bug-674.core-test/fn
                      test.clj:  704  clojure.test/test-var/fn
                      test.clj:  704  clojure.test/test-var
                      test.clj:   90  cider.nrepl.middleware.test/test-vars/fn/fn
                      test.clj:  674  clojure.test/default-fixture
                      test.clj:   90  cider.nrepl.middleware.test/test-vars/fn
                      test.clj:  674  clojure.test/default-fixture
                      test.clj:   86  cider.nrepl.middleware.test/test-vars
                      test.clj:  103  cider.nrepl.middleware.test/test-ns
                      test.clj:  124  cider.nrepl.middleware.test/handle-test/fn
                      AFn.java:  152  clojure.lang.AFn/applyToHelper
                      AFn.java:  144  clojure.lang.AFn/applyTo
                      core.clj:  624  clojure.core/apply
                      core.clj: 1862  clojure.core/with-bindings*
                   RestFn.java:  425  clojure.lang.RestFn/invoke
                      test.clj:  122  cider.nrepl.middleware.test/handle-test
                      test.clj:  161  cider.nrepl.middleware.test/wrap-test/fn
                middleware.clj:   17  clojure.tools.nrepl.middleware/wrap-conj-descriptor/fn
                   inspect.clj:   77  cider.nrepl.middleware.inspect/wrap-inspect/fn
                middleware.clj:   17  clojure.tools.nrepl.middleware/wrap-conj-descriptor/fn
                   session.clj:  192  clojure.tools.nrepl.middleware.session/session/fn
                middleware.clj:   17  clojure.tools.nrepl.middleware/wrap-conj-descriptor/fn
               macroexpand.clj:   34  cider.nrepl.middleware.macroexpand/wrap-macroexpand/fn
                middleware.clj:   17  clojure.tools.nrepl.middleware/wrap-conj-descriptor/fn
                  complete.clj:   47  cider.nrepl.middleware.complete/wrap-complete/fn
                middleware.clj:   17  clojure.tools.nrepl.middleware/wrap-conj-descriptor/fn
                   apropos.clj:   97  cider.nrepl.middleware.apropos/wrap-apropos/fn
                middleware.clj:   17  clojure.tools.nrepl.middleware/wrap-conj-descriptor/fn
                      info.clj:  230  cider.nrepl.middleware.info/wrap-info/fn
                middleware.clj:   17  clojure.tools.nrepl.middleware/wrap-conj-descriptor/fn
                  resource.clj:   22  cider.nrepl.middleware.resource/wrap-resource/fn
                middleware.clj:   17  clojure.tools.nrepl.middleware/wrap-conj-descriptor/fn
                     trace.clj:   35  cider.nrepl.middleware.trace/wrap-trace/fn
                middleware.clj:   17  clojure.tools.nrepl.middleware/wrap-conj-descriptor/fn
                 classpath.clj:   21  cider.nrepl.middleware.classpath/wrap-classpath/fn
                middleware.clj:   17  clojure.tools.nrepl.middleware/wrap-conj-descriptor/fn
                    server.clj:   18  clojure.tools.nrepl.server/handle*
                    server.clj:   27  clojure.tools.nrepl.server/handle/fn
                      core.clj: 1910  clojure.core/binding-conveyor-fn/fn
                      AFn.java:   18  clojure.lang.AFn/call
               FutureTask.java:  334  java.util.concurrent.FutureTask$Sync/innerRun
               FutureTask.java:  166  java.util.concurrent.FutureTask/run
       ThreadPoolExecutor.java: 1145  java.util.concurrent.ThreadPoolExecutor/runWorker
       ThreadPoolExecutor.java:  615  java.util.concurrent.ThreadPoolExecutor$Worker/run
                   Thread.java:  724  java.lang.Thread/run

Finally, some probably irrelevant system information: Here's the first line in my *cider-repl*:

; CIDER 0.7.0alpha (package: 20140723.1059) (Java 1.7.0_25, Clojure 1.6.0, nREPL 0.2.3, cider-nrepl 0.7.0-snapshot)

I'm running on OSX 10.9.4, here's my emacs-version:

GNU Emacs 24.3.1 (x86_64-apple-darwin13.1.0, NS apple-appkit-1265.19) of 2014-04-21 on <hostname>

Ah. It sounds like #648 because it is exactly the same issue -- only outside of a test is assertion rather than within one. As you suggested, @pgroce, the real question here is how best to provide feedback to the user, since the exception isn't actually a test error. I will have a look at this.

@jeffvalk Perhaps we should just display some message in the minibuffer?

I'm not sure that's enough indication of where the problem occurred. Outside of a test assertion, I'm inclined to think that the best feedback would look more like an ordinary compile/eval error: highlight the s-expression and show the stacktrace. This implies that the test report buffer would not be shown in such cases.

Seems reasonable to me.

FWIW, I'd rather see the report buffer than the stacktrace buffer in this case, for a few reasons:

  1. When I run cider-test, I expect the report buffer to come up. If I want the stack trace, I can click on the hyperlinked exception.
  2. If there are multiple tests, I still care whether/how they passed/failed.

That leaves what to highlight. IMO it would ideally be the line in the test that triggered the exception. Again, this is consistent with other tests. If that's infeasible, the highlighting @jeffvalk describes with other errors would be fine, too, but I'd still prefer seeing the report buffer.

All that said, I'll be happy with anything that doesn't throw an error, so I yield to your good judgment. :)

I'll defer to @jeffvalk on this.

After looking into this, I agree with you, @pgroce. I have a straightforward fix that does just this. There's one more thing I want to look into for consistency, then I'll push the fix.

Fixed in cider-nrepl f151993.