Skip to content

Instantly share code, notes, and snippets.

@loganlinn
Last active August 29, 2015 14:15
Show Gist options
  • Save loganlinn/dc85c37391ddddf52408 to your computer and use it in GitHub Desktop.
Save loganlinn/dc85c37391ddddf52408 to your computer and use it in GitHub Desktop.
Using Karma Test Runner with ClojureScript

Configure (node) Dependencies

{:plugins [[lein-npm "0.4.0"]]
  :node-dependencies [[karma "0.12.28"]
                      [karma-chrome-launcher "0.1.7"]
                      [karma-firefox-launcher "0.1.3"]]}
$ lein npm install

(or go package.json route)

Add cljs-karma to build

The cljs-karma.cljs file bridges ClojureScript test reporting to Karma's. Add this file to your ClojureScript's test build. I put mine directly in test/ directory at root of project.

Configure Karma

Generate karma config file

$ ./node_modules/karma/bin/karma init

In karma.conf.js, add specify adapter.js as last item in files: (this should be eventually replaced by a karma framework)

files: [
  // ...
  {pattern: 'path/to/adapter.js', included: true, served: true, watched: false}
],

Run

Time to (auto) compile your project and start Karma to run your tests.

Install lein-karma-test for convenient lein karma start command

or run directly from node_modules dir:

$ ./node_modules/karma/bin/karma start
(function(window) {
window.__karma__.start = cljs_karma.create_start(window.__karma__);
})(window);
(ns cljs-karma
(:require
[clojure.string :as str]
[cemerick.cljs.test :as test]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Private: Karma utils
(defn karma-result! [m] (.result js/__karma__ (clj->js m)))
(defn karma-complete! [m] (.complete js/__karma__ (clj->js m)))
(defn karma-info! [m] (.info js/__karma__ (clj->js m)))
(defn karma-log [type msg] (.info js/__karma__ #js {:log msg :type (name type)}))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Private: cljs.test utils
(defn total-test-count []
(reduce + (map count (vals @test/registered-tests))))
(defn- print-some-testing-contexts
"Prints testing-context-str if non-blank"
[test-env]
(let [ctx-str (test/testing-contexts-str test-env)]
(when-not (str/blank? ctx-str)
(println ctx-str))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Private: cljs.test -> karma reporting bridge
(defmethod test/report :end-test-var
[{:keys [test-env test-name var] :as m}]
(karma-result!
{:id ""
:description (name test-name)
:suite [(name (namespace test-name))]
:success true
:time 0 ;; aren't giving timing info :(
:log []}))
(defmethod test/report :fail
[{:keys [file test-env] :as m}]
(test/inc-report-counter test-env :fail)
(karma-result!
{:id ""
:description (str "FAIL in " (test/testing-vars-str m))
:suite [file]
:success false
:time 0 ;; aren't giving timing info :(
:log [(with-out-str
(print-some-testing-contexts test-env)
(when-let [message (:message m)] (println message))
(println "expected:" (pr-str (:expected m)))
(println " actual:" (pr-str (:actual m))))]}))
(defmethod test/report :error
[{:keys [test-env file] :as m}]
(test/inc-report-counter test-env :error)
(karma-result!
{:id ""
:description (str "ERROR in" (test/testing-vars-str m))
:suite [file]
:success false
:time 0
:log [(with-out-str
(print-some-testing-contexts test-env)
(when-let [message (:message m)] (println message))
(println "expected:" (pr-str (:expected m)))
(print " actual: ")
(let [actual (:actual m)]
(if (instance? js/Error actual)
(println (.-stack actual))
(prn actual))))]}))
(defn test-summary [test-env]
(let [ks [:test :pass :fail :error]
stats (merge-with + (select-keys test-env ks) (select-keys @(:async test-env) ks))
{:keys [test pass fail error]} stats]
(str "Ran " test " tests containing " (+ pass fail error) " assertions")))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Public
(defn ^:export run-all-tests [karma env config]
(test/set-print-fn! (constantly nil))
(karma-info! {:total (total-test-count)})
(let [results (test/run-all-tests)]
(test/on-testing-complete
results
(fn [test-env]
(karma-log :info (test-summary test-env))
;; Let final :end-test-var to come in (cemerick/clojurescript.test#87)
(js/setTimeout #(karma-complete! {}) 10)))))
(defn ^:export create-start [karma env]
(fn [config]
(run-all-tests karma env config)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment