This question is brought to you by TDD in Cider. I was a Luminus user before I knew what TDD was. Luminus by default builds a structure with /tests/<my-project>
as the path, and includes the appropriate things in project.clj
to handle this. This makes sense to me, because it means I can easily omit those paths from my production war/jar. However, Cider says that it uses a “leiningen convention” and by default expects the files to be siblings to file they are based upon with a -test.clj
filename. I can change the cider function that infers namespaces of tests, but if that -test.clj convention is more prevalent than just cider, it may have unseen merit. How do you arrange your testing namespaces? Do you have separate places for those tests which make sure all the functions work, and those functions which test a certain workflow (e.g. “what a user does”)?
There are two separate aspects at play here. One is how a test namespace’s name relates to the namespace under test’s, the other is where these test namespaces are put on the classpath.
The most common convention by far in the Clojure world (folks correct me if I’m wrong but I hardly ever see anything else) is that a foo.bar
namespace has its tests in foo.bar-test
. It’s also quite common to name the test for the baz
var baz-test
, but there you see more variation in how people do it.
(ns foo.bar)
(defn baz [] ,,,)
(ns foo.bar-test
(:require [clojure.test :refer :all]
[foo.bar :as bar]))
(deftest baz-test
(is (= (bar/baz) ,,,)))
Luminus is interesting in that instead of foo.bar-test
it uses foo.test.bar
, and instead of baz-test
it uses test-baz
.
(ns foo.test.bar
(:require [clojure.test :refer :all]
[foo.bar :as bar]))
(deftest test-baz
(is (= (bar/baz) ,,,)))
These files follow the Clojure naming conventions, so they end up in foo/bar_test.clj
or foo/test/bar.clj
, however they are not usually heaped in with the rest of the source files under src
. Instead they are commonly placed in test
, or test/clj
if you have a clj+cljs app. This is also what luminus does, so you end up with for instance
# common convention
test/foo/bar_test.clj
# luminus
test/clj/foo/test/bar.clj
And so you’d have either test
or test/clj
on the classpath
;; Leiningen
:test-paths ["test/clj"]
;; deps.edn
:paths ["src" "test/clj"]
Personally I’ve been opting to put my main Clojure tests under test/unit
, with any supporting code (e.g. custom assertions and test helpers) under test/support
. This also leaves space to add other test types or suites like test/cljs
, or test/api
or test/integration
.
(On a side note about testing conventions, I’ve come to always add [clojure.test :refer :all]
, even though I generally avoid :refer :all
anywhere else, but in my tests I want the testing API to always be available, including are
, run-tests
, etc. In ClojureScript tests this doesn’t work and I either :as t
or :refer [all-the-things]
,or both.)
Thanks for that comprehensive overview. It sounds like there’s a good deal of flexibility available to me to choose from, although there are some informal standards. Dmitri, when designing Luminus, has imparted his own conventions (which, as an aside, are not what Cider or CLJ-Refactor seem to consider standard). So basically, I need to put some thought into how I want test structure to be for my teams.
This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.