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))