In the first part of this blog I showed a way of loading figwheel from an nREPL while keeping the figwheel code separate from the generic build used to build for production.
One of the things I wanted to ensure in my lein project was that any Clojurescript test code is kept separate from the production code to be shipped.
I decided to use the doo library to run my cljs tests. I experimented with using the cljsbuild plugin with a js script and phantomjs to run cljs tests as described here but I found this approach didn’t always report failures in async tests correctly.
To set up doo you need to add the following entries to the project.clj
file:
:profiles { :dev { ... :source-paths ["dev/src" "src-cljs" "test-cljs"] ; add test dir :dependencies [... [lein-doo "0.1.6"]] :plugins [[lein-doo "0.1.6"]]}}
As well as adding lein-doo
to the dependencies and the plugins for only the :dev
profile, you need to add the directory containing the test code to the source paths. In my case I am keeping my test code in a directory called ‘test-cljs’.
In addition lein-doo needs a test runner to bootstrap it. Therefore I added a test-runner
namespace that calls the doo-tests
function to run the test namespaces (in this case only core-test
).
(ns blogcljsfigwheel.test-runner (:require [doo.runner :refer-macros [doo-tests]] [blogcljsfigwheel.core-test]))
(enable-console-print!)
(doo-tests 'blogcljsfigwheel.core-test)
I also needed to add the cljsbuild config for the test namespaces to the project file to ensure the test code is transpiled to JavaScript.
:cljsbuild {:builds {... :test {:source-paths ["src-cljs" "test-cljs"] :compiler {:main "blogcljsfigwheel.test-runner" :output-to "resources/private/js/unit-test.js" :optimizations :whitespace :pretty-print true}}}}
If you have phantomjs installed on your path you can then run the tests using lein doo phantom test.
As you can see the test build outputs to the resources/private
directory whereas I configured the app
build to output to the target directory:
:cljsbuild {:builds {:app {:source-paths ["src-cljs"] :compiler {:main "blogcljsfigwheel.core" :output-to "target/cljsbuild/public/js/compiled/blogcljsfigwheel.js" :output-dir "target/cljsbuild/public/js/compiled/out" :asset-path "js/compiled/out"}} ... }
In order to package the Clojurescript in the uberjar I also needed to add:
:profiles {:uberjar {:aot :all :cljsbuild {:builds {:app {:jar true :compiler {:optimizations :advanced}}}} :prep-tasks ["compile" ["cljsbuild" "once" "app"]]} ... }
The prep-tasks ensure that the cljsbuild is run for the app build when the uberjar is built using lein uberjar
.