Fork me on GitHub
#conjure
<
2022-07-15
>
Martynas M07:07:08

I got this strange frustration about Clojure on nvim (via conjure). I've configured LSP, language servers, highlighting... and now I still can't switch to nvim. It's faster, sure. But I'm so used to simply press <localleader>tn to run namespace's tests and then look into the tests buffer to find red lines or jump to that test from a test result buffer... How do I even find the failing test in a failing namespace? What would one do when a test fails? There was some guy that tried to rerun the failing test by running the expression in a marked other buffer position. But to find that line and position you have to manually look into the test log buffer (and hope it doesn't have too much text or many failing tests) and find the failing test line in an unhighlighted test output. And then you have to remember the number, jump to that file via FZF or other tool, then jump to that line and by this point you probably already forgot what is the output of the test. So that means that you have to keep the test result buffer around (which I do on Spacemacs anyway as I need to look at the result constantly) but as you evaluate your form then the test results are slowly getting buried in the log outputs (even if nothing is printed). I think I miss the point somehow. What did I do wrong? How do you do this? Maybe there is a better way...?

Proctor13:07:26

I use the nREPL shortcuts to run tests (https://github.com/Olical/conjure/blob/master/doc/conjure-client-clojure-nrepl.txt), although it doesn’t look to have the run failing test(s)

Proctor13:07:06

If there is a test I am touching and fixing, I put a global mark down and use that for a jump point to run the tests again and jump to there

Proctor13:07:33

maybe there is an idea of run test at mark in the same way there is a eval at mark that could be added onto Conjure (either directly or through a custom mapping that does the jump run test then jump back)

Martynas M14:07:49

I think that you were mentioning it before in my other message. But how do I find that test so that I could mark it? What if the test file is 1000 lines long... (I have a couple of these namespaces)

NoahTheDuke14:07:51

what plugin are you using in vim that doesn't work in neovim?

Martynas M14:07:22

I use nvim. It's just less typing to type vim but I also didn't mention vim.

NoahTheDuke15:07:57

Okay, then where does <localleader>tn come from?

Proctor15:07:39

test namespace in Conjure, likely

Proctor15:07:30

there is also <localleader>gd to jump to definition which works in Conjure’s log buffer

Martynas M15:07:09

<localleader> is what you specify in your .config/nvim/init.vim file: let maplocalleader="-" I have it set to - and it would be confusing for you if I'd say -tn or -tN. And then Conjure uses that shortcut to provide this kind of keys (this is after pressing -t and waiting (very nice plugin folke/which-key.nvim)):

NoahTheDuke15:07:11

Ah, I think I'm misunderstanding the original message

NoahTheDuke15:07:55

you're asking about a workflow that allows you to go from "failing test in the conjure log" to "originating deftest"?

NoahTheDuke15:07:20

Cool, that makes sense

Martynas M15:07:30

No. I ask about "when I run tests in alternate namespace, how do I go to that first failing test?" And also I asked "when I run tests, how do I rerun the failing ones", but this was already answered the same twice. And it would work to use a global mark but I was still a little unhappy.

NoahTheDuke15:07:44

Okay. To be clear, you're in martynas.example-ns , you press <localleader>tn to run the tests in martynas.example-ns-test, the hover window or your log shows FAIL in (example-test-1) (example_ns_test.clj:123), you want a key-combo to go directly to example-test-1?

Martynas M15:07:27

Yes. Or an alternative that I could use. Or something else. How do you do it? Maybe there is an even better way that I'm blind to. Also a side note: Conjure works quite weirdly that it has N and n execution modes where it executes the current namespace as if it would be a test namespace. That is weird to me. I would also like that by pressing <localleader> I would always execute the _test.clj file and not the current file. But that's a minor thing and I could configure this myself.

NoahTheDuke15:07:12

I use https://github.com/tpope/vim-projectionist which has defaults for clojure and press :A to switch automatically to the alternative file. (I don't know if there's a way to do that in conjure.) Once in the file, I press 123G, where 123 is the line number and G moves the cursor to that line number

Martynas M15:07:45

Ah, but you still have to figure out the line number yourself... I see.

Proctor15:07:21

the execute tests in current namespace can be useful when fixing up tests

NoahTheDuke15:07:01

I split nvim vertically and have one of the windows be the log at all times, so I'm constantly looking at it.

NoahTheDuke15:07:09

Looking at the line number isn't too hard

NoahTheDuke15:07:41

I bet there's some way Conjure could parse the fail messages and then add to the quickfix list the files and line locations, but that's a bit of work

Martynas M15:07:53

In Spacemacs I am presented by a test result buffer where I can jump to next test result with J and K. And then I can press <enter> to go to that exact file and line. That was basically what I wanted. Example how it looks like in CIDER:

NoahTheDuke15:07:24

That's pretty fuckin cool. I bet conjure could add that, just gotta build it.

Martynas M15:07:09

This can be a separate plugin even. gtg, will reply later

👍 1
NoahTheDuke15:07:54

(defun cider-test-jump (&optional arg)
  "Find definition for test at point, if available.
The prefix ARG and `cider-prompt-for-symbol' decide whether to
prompt and whether to use a new window.  Similar to `cider-find-var'."
  (interactive "P")
  (let ((ns   (get-text-property (point) 'ns))
        (var  (get-text-property (point) 'var))
        (line (get-text-property (point) 'line)))
    (if (and ns var)
        (cider-find-var arg (concat ns "/" var) line)
      (cider-find-var arg))))
not to speak too boldly, but this seems broadly doable

Martynas M17:07:11

Actually I thought about how I would make a plug-in that would make all of this without a custom buffer type. If I would create a namespace-transformation function that could extract only the testcases then: 1. I could use a temporary buffer as the whole test result and the state at the same time 2. I could narrow-down tests by deleting tests that pass 3. I could jump to tests because it would be the same Clojure buffer and these would be imports i.e. 1. Create a new temporary clojure buffer 2. Transform the namespace into non-nested testing calls as paragraphs 3. Each of "my-testing" calls would either remove the testcase from the buffer or display output somewhere (probably in the same buffer) 4. This is already possible because Conjure intro does this to the buffer

Olical10:07:50

Just to finally follow up on this without being in the loop: There's no way with Conjure to jump to the first / last failing test right now. If that was implemented I'd probably populate the quickfix list with locations and let you hop between them using vim mappings rather than invent anything new myself. (quickfix is built for that scenario). I don't get that feedback right now in data I don't think? So I'd have to do some work to somehow capture or report what failed and where, maybe CIDER has some features that would do this. My point being: The data isn't already in memory or in the test eval response, so I can't just enable it quickly, it'd take a bit of research and rewriting but not impossible... I think.

Martynas M10:07:49

Would it be ok to capture the system-out like this:

(binding [*out* (java.io.PrintWriter. (java.io.ByteArrayOutputStream.))]
  ;;call test methods here
)
And then return a tuple?

Proctor11:07:06

Looking at it, Clojure has a dynamic var of *test-out*, and a macro that does that: https://github.com/clojure/clojure/blob/master/src/clj/clojure/test.clj#L273

(defmacro with-test-out
  "Runs body with *out* bound to the value of *test-out*."
  {:added "1.1"}
  [& body]
  `(binding [*out* *test-out*]
     [email protected]))

Proctor11:07:10

that way you keep the test result output distinct from any other output that may litter your tests

Martynas M12:07:15

Oh right. I forgot that everything can pollute the output. But then I at least hope that they rebind that *out* inside. Because if they don't then the output would still be polluted :thinking_face:

Proctor13:07:40

looking at the code, it is for outputting the results

Proctor13:07:49

after all the tests have been run