Reputation: 899
I would like to build a jar file containing a suite of clojure.test
tests, and then use lein test
to run those tests. As far as I can tell, :test-paths
only supports paths to test source, not test jars.
Is there a way to accomplish this?
Upvotes: 1
Views: 486
Reputation: 29958
You can do this by manually creating a test runner. Suppose you have a project demo
and a testing ns tst.demo.core
like so:
(ns tst.demo.core
(:use demo.core clojure.test)
(:require
[tupelo.core :as t] ))
(t/refer-tupelo)
(deftest t1 (println "test t1"))
(deftest t2 (println "test t2"))
Under the src/demo
directory, create a test driver demo.tst
like so:
(ns demo.tst
(:use clojure.test)
(:require
[tupelo.core :as t]
[tst.demo.core :as tdc] )
(:gen-class))
(t/refer-tupelo)
(defn pi [] (println 3.14))
(spyx (pi))
(spyx (#'pi))
(defn -main
[& args]
(spyx (ns-interns 'tst.demo.core))
(let [tst-vars (vals (ns-interns 'tst.demo.core))]
(spyx tst-vars)
(doseq [tv tst-vars]
(tv))))
We can run our driver which will call all of our tests in tst.demo.core
:
> lein run -m demo.tst
(pi) => 3.14
((var pi)) => 3.14
(ns-interns (quote tst.demo.core)) => {t1 #'tst.demo.core/t1, t2 #'tst.demo.core/t2}
tst-vars => (#'tst.demo.core/t1 #'tst.demo.core/t2)
test t1
test t2
We digress a bit to discuss the Clojure var
. The var
is like a pointer from a symbol like pi
to the function that prints 3.14
. Normally we don't even realize the var
is there, as with the first printout:
(pi) => 3.14
We invoked the pi
function, which returned the value 3.14, as usual.
However, we can get a reference to the var
for the pi
function using the wither #'pi
or (var pi)
. We then invoke the pi
function using the var, not the symbol pi
. We see:
((var pi)) => 3.14
We use the ns-interns
to get a map from symbols to vars in the tst.demo.core
namespace (note: it is critical that we have :require [tst.demo.core ...]
at the top of the file in the ns
form). We printout this map:
(ns-interns (quote tst.demo.core)) => {t1 #'tst.demo.core/t1, t2 #'tst.demo.core/t2}
We only need the vars themselves, so we grab them and save into tst-vars
:
tst-vars => (#'tst.demo.core/t1 #'tst.demo.core/t2)
Note that each (dotest ...)
form in the testing ns tst.demo.core
creates a function that is invoked during lein test
. We can invoke these functions ourselves, using the vars we just retrieved. This is what the doseq
loop does, and we see the output of our mock test functions t1
and t2
:
test t1
test t2
The final step is to designate demo.tst
as the main ns in project.clj
via
:main demo.tst
which should allow you to create a uberjar and run it:
> java -jar target/uberjar/demo-0.1.0-SNAPSHOT-standalone.jar
(pi) => 3.14
((var pi)) => 3.14
(ns-interns (quote tst.demo.core)) => {t1 #'tst.demo.core/t1, t2 #'tst.demo.core/t2}
tst-vars => (#'tst.demo.core/t1 #'tst.demo.core/t2)
test t1
test t2
Upvotes: 1