It is possible to write and execute unit tests using Planck.
Let's say you have a namespace with a function you'd like to test.
(ns foo.core) (defn square [x] (+ x x))
You can test foo.core by writing a test namespace:
(ns foo.core-test (:require [cljs.test :refer-macros [deftest is]] [foo.core])) (deftest test-square (is (= 0 (foo.core/square 0))) (is (= 9 (foo.core/square 3))))
Then you can run the unit tests using run-tests:
cljs.user=> (cljs.test/run-tests 'foo.core-test) Testing foo.core-test FAIL in (test-square) (:5:1) expected: (= 9 (foo.core/square 3)) actual: (not (= 9 6)) Ran 1 tests containing 2 assertions. 1 failures, 0 errors. nil
If you fix the definition of square to make use of * instead of +, then you can run the tests again and see thing they pass:
cljs.user=> (cljs.test/run-tests 'foo.core-test) Testing foo.core-test Ran 1 tests containing 2 assertions. 0 failures, 0 errors. nil
The cljs.test library provides a mechanism for writing custom asserts that can be used with the is macro—in the form of an assert-expr defmulti.
To define your own assert, simply provide a defmethod for cljs.test$macros/assert-expr. Here's an example:
If you evaluate (is (char? nil)) you will get a cryptic error report:
ERROR in () (isUnicodeChar@file:269:12) expected: (char? nil) actual: #object[TypeError TypeError: null is not an object (evaluating 'ch.length')]
You can define a custom assert for this situation:
(defmethod cljs.test$macros/assert-expr 'char? [menv msg form] (let [arg (second form) result (and (not (nil? arg)) (char? arg))] `(do (if ~result (cljs.test/do-report {:type :pass :message ~msg :expected '~form :actual (list '~'char? ~arg)}) (cljs.test/do-report {:type :fail :message ~msg :expected '~form :actual (list '~'not (list '~'char? ~arg))})) ~result)))
With this, (is (char? nil)) yields:
FAIL in () (eval@[native code]:NaN:NaN) expected: (char? nil) actual: (not (char? nil))