Kaocha + namespace.repl/refresh

Hi Clojure people,

I want to run Kaocha in REPL instead of starting it from cold each time.

My deps.edn:

{:paths ["src/main/clojure"]
 :deps {org.clojure/clojure {:mvn/version "1.11.1"}
        ...}
 :aliases
 {:dev
  {:extra-paths ["src/main/test"]
   :extra-deps  {org.clojure/tools.namespace {:mvn/version "1.3.0"}
                 org.clojure/tools.deps.alpha {:git/url "https://github.com/clojure/tools.deps.alpha"
                                               :git/sha "e4fb92eef724fa39e29b39cc2b1a850567d490dd"}
                 lambdaisland/kaocha {:mvn/version "1.71.1119"}
                 org.clojure/test.check {:mvn/version "1.1.1"}}}
...

And then in clj -M:dev REPL:

(require '[kaocha.repl :as k])
(require '[clojure.tools.namespace.repl :refer [refresh]])
(refresh)
(k/run 'my.app.abc-test {:config-file "tests.edn"})

And then when I hit (refresh), if I changed abc_test.clj then namespace my.app.abc-test gets refreshed. But when I change abc.clj, namespace my.app.abc is never refrefreshed. Do you know why?

Thank you.

P.S. I know about Kaocha watch but I don’t like it since I setup my editor to save automatically and the constant test runs are annoying…

Hard to say without more detail and perhaps exact steps to reproduce in a public repo on GitHub, but I will say that tools.namespace.repl/refresh can break in all sorts of ways and I generally recommend people just don’t use it – and instead develop a REPL workflow where you eval every top-level form as you change it.

I eval forms without even saving files – alt+enter in Calva – and that keeps my REPL always up to date.

I also never type into a REPL. I either evaluate source code (or test code) or I write a comment form containing expressions I want to try out or eval into the REPL (a so-called Rich Comment Form, coined by Stu Halloway, because Rich Hickey uses that technique extensively). That way you always have a record of what you tried – and Calva can add results of evaluation as ;;=> comments following each expression you evaluate.

It’s a very different workflow to working in other languages, but it really is worth it for Clojure.

Hi Sean,

Thank you for the answer.

Calva + REPL development workflow is fantastic. But if I already have tests and I’m modifying the tested functions for some reason, it makes more sense just re-run the tests.

I’ve just disabled autosaving in my editor and tried to work with Kaocha in --watch mode and it works great (tools.namespace.repl/refresh used automatically by Kaocha works just fine). It’s not ideal solution since I still would prefer to run the tests manually but it’s better than nothing.

I’m thinking that tools.namespace.repl/refresh might not be picking up changes in src/main/clojure because I’m not using default paths (src and test directory in project root)… I’ll try a few more tests.

Do you know is it possible specify in deps.edn some commands to run at the beginning of REPL when REPL starts? I was thinking that it would be cool if I jumped to REPL via clj -M:dev with already required modules (with (require '[kaocha.repl :as k]) command automatically run at the beginning).

A custom user namespace that is on the class path when the repl is started can be used to load Clojure code as the REPL starts

I typically create a dev/user.clj file that defines a user namespace and loads an assortment of tools and libraries

That can be done via a hotkey in Calva – to run tests in the current ns (i.e., for the test file you are editing). No need to switch context or wait for a watcher etc.

(I have a hotkey bound to a snippet that runs just the “current” test – the top-level form I am editing – so I can modify a test, eval the test without having to save the file and then run just that test but that’s not “out of the box”).

I’ve just started using it and it’s fantastic, thank you. I quickly realized I can have fun like:

(ns user
  (:require [kaocha.repl :as krepl]
            [clojure.tools.namespace.repl :as nsrepl]))

(def r nsrepl/refresh)

Because (refresh) is too long to type ;-).

Cool, thank you. I’m not used to be “Jack-in” so I didn’t even realized. Do you have to “Evaluate current form” before you run tests for a given function? In other words, do tests run against what is def-ed in REPL or the current code?

Editor test runners and running tests in the repl use the state of the repl, so all the code (src & test) has to be evaluated (loaded)

Using a test runner on the command line will read the code from all the files on the class path

tools.namespace.repl/refresh is a little extreme and is not needed (only perhaps in the edge case of significant refactor has been done and there are lots of outdated definitions (especially tests) that were not unevaluated - or restart the repl instead)

The editor should have a command to evaluate the whole file (sometimes called loading), this will read all the code and update the repl state

More commonly test and source functions are evaluated when as they are written or changed. It seems Calva used ctrl + enter to evaluate an expression (form), so this can be used to evaluate a test functions or a src function straight after it’s changed

These references may be of use

The goal with a REPL-focused workflow is that the state of the REPL is always kept up-to-date with your code changes – as I noted, I eval each top-level form as I change it, often without even saving the file, so my REPL state tracks my editor state (and is often ahead of my files-on-disk state).

If you haven’t yet explicitly evaluated your source code, when you evaluate your test code, that will require (load/evaluate) the source code it depends on – so you generally only need to worry about eval’ing (changes to) the file you are currently editing, before switching to another file.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.