Fork me on GitHub
#inf-clojure
<
2022-03-30
>
apt20:03:05

Hi folks. Is anyone rebinding #'clojure.test/*test-out* for getting test output in the repl buffer? I replicated the nrepl workaround: https://github.com/nrepl/nrepl/blob/a057874cd3bfc83e465cc163fbc1d4c00223e1b1/src/clojure/nrepl/middleware/interruptible_eval.clj#L93-L99 with this:

(inf-clojure-eval-string "(do (require '[clojure.main :as m])
                                (clojure.main/repl 
                                                :init #(do
                                                           ;; The :init hook replicates what clojure.main uses as an initial binding set, so it's good to repeat that.
                                                           ;; From 
                                                           (apply require m/repl-requires)
                                                           ;; Workaround for rebinding clojure.test/*test-out*.
                                                           ;; For details, see \"
                                                           (require 'clojure.test)
                                                           (let [bindings (into (get-thread-bindings)
                                                                                {#'clojure.test/*test-out* *out*})]
                                                             (pop-thread-bindings)
                                                             (push-thread-bindings bindings)))))")
however, I”m getting a stack overflow error when running a state-flow test [1] Unfortunately the code is private and I don’t have a minimum reproducible example, but I’d like to know if something seems wrong with my attempt to do the same (the code is similar to nrepls, but it’s not equal). [1]: https://github.com/nubank/state-flow/

dpsutton20:03:21

i always run the test as (binding [*test-out* *out*] (run-tests)) or an individual test

apt20:03:47

this seem safer. let me try.

dpsutton20:03:39

i use registers and have a send register to repl function. I’m not sure if that’s made it into inf or i just keep that as separate

dpsutton20:03:59

but i always have that run-tests form in register t and then have individual tests in register i

apt20:03:25

interesting. I still get the stack overflow error. This only happens when I bind clojure.test/*test-out*. I suppose this is a bug in state-flow. I’ll try to investigate it. error: https://gist.github.com/Andre0991/d771b0823e92b42b90038d9bd82da113 I was still using the nrepl approach in this gist but the error I got now is the same, anyway It gets stuck in this:

clojure.core/fn (core_print.clj:317)
    clojure.lang.MultiFn.invoke (MultiFn.java:234)
    clojure.core$pr_on.invokeStatic (core.clj:3675)
    clojure.core$pr_on.invoke (core.clj:3669)
    clojure.core$print_sequential.invokeStatic (core_print.clj:66)
    clojure.core$fn__7411.invokeStatic (core_print.clj:225)
    clojure.core/fn (core_print.clj:225)
    clojure.lang.MultiFn.invoke (MultiFn.java:234)
    clojure.core$pr_on.invokeStatic (core.clj:3675)
    clojure.core$pr_on.invoke (core.clj:3669)
    clojure.core$print_prefix_map$fn__7414.invoke (core_print.clj:233)
    clojure.core$print_sequential.invokeStatic (core_print.clj:66)
    clojure.core$print_prefix_map.invokeStatic (core_print.clj:229)
    clojure.core$print_map.invokeStatic (core_print.clj:238)
    clojure.core$fn__7443.invokeStatic (core_print.clj:266)
    clojure.core/fn (core_print.clj:263)

apt20:03:47

ah, and actually, binding the var as you did still redirected the output to the original repl, not inf-clojure’s

dpsutton20:03:16

if you remove all tooling and just use a socket repl you can have the best way to come up with a minimal example

dpsutton20:03:36

nc localhost port and go from there fore the bug report

dpsutton20:03:00

but at this point it’s not inf-clojure’s fault it seems. You could ask in #clojure for more eyes

apt20:03:47

yeap, agreed. I guess it’s not related to inf-clojure either in any case, thanks!

dpsutton20:03:47

for sure. interested in how it works out

dpsutton20:03:01

might have to add that binding to my clojure.main/repl invocation

apt20:03:41

yeap, it’s useful I also set pprint as the default printer https://github.com/Andre0991/dotfiles/blob/master/elisp/apt-inf-clojure.el#L19

dpsutton20:03:03

yeah i use this:

(clojure.main/repl
 :prompt (fn [] (printf "%s=> " (peek (str/split (str *ns*) #"\."))))
 :read server/repl-read
 :print fipp/pprint)

dpsutton20:03:25

annoyingly, with this form

(clojure.main/repl
 :init   (fn [] {#'clojure.test/*test-out* *out*})
 :prompt (fn [] (printf "%s=> " (peek (str/split (str *ns*) #"\."))))
 :read server/repl-read
 :print fipp/pprint)
the behavior is not what i want
bookmark-test=> (with-bindings {#'*test-out* *out*} (run-tests)) ;; using manual bindings

Testing metabase.api.bookmark-test

FAIL in (foo) (NO_SOURCE_FILE:36)
expected: 1
  actual: 2
    diff: - 1
          + 2

Ran 3 tests containing 21 assertions.
1 failures, 0 errors.
{:test 3, :pass 20, :fail 1, :error 0, :type :summary}
bookmark-test=> (run-tests) ;; relying on bindings in #init
{:test 3, :pass 20, :fail 1, :error 0, :type :summary}
bookmark-test=> 

apt20:03:05

yeah. for some reason, the (get-thread-bindings) stuff seems necessary. but I never took the time to learn why, just blindly copied this snippet of code from nrepl 🤷