cider 2024-11-13

i develop an alternative test framework called #lazytest that supports running tests from the repl. i don't use emacs or CIDER so I'm unfamiliar with how it works, but someone has asked for help on getting the CIDER keybinds/workflow to integrate with lazytest. i use neovim and have instructions for neovim (conjure) and calva and intellij, but i'd love for some help with CIDER. can one of you help me/us?

in short, you can call (lazytest.repl/run-all-tests) to run all loaded tests, (lazytest.repl/run-tests ) to run the tests in a given namespace, or (lazytest.repl/run-test-var #') to run a given var's test (either a defdescribe test var or a function with :test metadata, which lazytest supports). All three functions also support an optional trailing config map, so you can say (lazytest.repl/run-test-var #'example-var {:reporter [lazytest.reporters/nested]}) and it "just works"

i know CIDER has a whole test integration toolbox for looking at stack traces and jumping to errors etc. I don't expect to copy all of that, just a way to say "add X to your emacs config and you can run tests under your cursor with a keybind" or similar

so basically cider testing functionality allows you to run single test, all tests inside a ns and all tests in a project. Under the hood I think it uses clojure.test which runs all vars with a :test meta

that said you can easily create some elisp function to run whatever function you want runtime side like this :

(defun run-all-lazy-tests ()
  (interactive)
  (let* ((current-ns (cider-current-ns)))
    (cider-interactive-eval "(lazytest.repl/run-all-tests)"
                            nil
                            nil
                            `(("ns" ,current-ns)))))

those are interactive functions, so you can run them by command name or assign a keybinding

yeah, this is wholly separate from clojure.test, no overlap at all, so i can't rely on the clojure.test functionality

then maybe you can create a couple elisp functions like that for calling lazytest.repl functions

let me try to create those functions for your description

thank you, that's kind of you

these seams to work :

(defun lazy-tests-run-var ()
  (interactive)
  (let* ((current-ns (cider-current-ns))
         (var (cider-last-sexp)))
    (cider-interactive-eval (format "(lazytest.repl/run-test-var #'%s)" var)
                            nil
                            nil
                            `(("ns" ,current-ns)))))

(defun lazy-tests-run-ns ()
  (interactive)
  (let* ((current-ns (cider-current-ns)))
    (cider-interactive-eval (format "(lazytest.repl/run-tests '%s)" current-ns)
                            nil
                            nil
                            `(("ns" ,current-ns)))))

(defun lazy-tests-run-all ()
  (interactive)
  (let* ((current-ns (cider-current-ns)))
    (cider-interactive-eval "(lazytest.repl/run-all-tests)"
                            nil
                            nil
                            `(("ns" ,current-ns)))))

I tried them with :

(ns lazytest.repl)

(defn run-test-var [v] (println "Running" v))
(defn run-tests [ns] (println "Running ns" ns))
(defn run-all-tests [] (println "Running all tests"))

and seams to be printing the correct messages when I fire those commands

hell yeah, thank you so much

if you use this instead for the var one :

(defun lazy-tests-run-var ()
  (interactive)
  (let* ((current-ns (cider-current-ns))
         (var (cider--extract-test-var-at-point))
         (var-ns (first var))
         (var-name (second var)))
    (cider-interactive-eval (format "(lazytest.repl/run-test-var #'%s/%s)" var-ns var-name)
                            nil
                            nil
                            `(("ns" ,current-ns)))))
then you don't need to run the lazy-tests-run-var command with the cursor on the var name, you can do it on the body of the form. But I'm not sure it will work with your tests forms, to find the test var name cider does some fancy lookup for "the var" by looking at its highlighting 😅, and checks it contains :test meta

yeah, cider--extract-test-var-at-point doesn't quite work, i looked at that earlier. if there's an extract-root-form or similar then that could be used