If you look at the docs for defn
you’ll see that you can put a map between the doc string and the argument vector. And if you look at the implementation of the deftest
macro, you’ll see that it puts the tests into the :test
key of this map. Then that is where the test runner finds them. Which means you can put them there yourself w/o deftest
, if you fancy.
It can look a bit like so:
(defn- divizable?
"Is `n` divisable by `d`?"
{:test (fn []
(is (divizable? 49 7))
(is (not (divizable? 48 7))))}
[n d]
(zero? (mod n d)))
(comment
(divizable? 5 5)
;; => true
(divizable? 1 0)
;; => Execution error (ArithmeticException) at fizzy/divizable? (anagram.clj:22).
;; Divide by zero
)
(defn fizz-buzz
"FizzBuzz it"
{:test (fn []
(is (= 4
(fizz-buzz 4)))
(is (= ["Buzz" 11 "Fizz" "FizzBuzz"]
(map fizz-buzz [10 11 12 15])))
(is (= [1 2 "Fizz"]
(fizz-buzz 1 4)))
(is (= "FizzBuzz"
(nth (fizz-buzz) (dec 90))))
(is (= 100 (count (fizz-buzz)))))}
([n]
(cond
(divizable? n (* 3 5)) "FizzBuzz"
(divizable? n (* 3)) "Fizz"
(divizable? n (* 5)) "Buzz"
:else n))
([start end]
(map fizz-buzz (range start end)))
([]
(fizz-buzz 1 101)))
(comment
(fizz-buzz 4)
;; => 4
(fizz-buzz 1 15)
;; => (1 2 "Fizz" 4 "Buzz" "Fizz" 7 8 "Fizz" "Buzz" 11 "Fizz" 13 14)
(fizz-buzz))
Using Calva, I can have the cursor anywhere inside the defn
form and Run Current Test and it will run these tests. I’m pretty sure CIDER has a similar feature. In Calva the default keybinding allows me to hold the ctrl
and alt
keys down, and then press c
, t
to execute this. This makes it very quick to TDD my way towards an implementation. And since tests take no arguments I can also put the cursor adjacent to the (is ...)
form and Evaluate Current Sexpr/Form to run a particular assertion.
They are quite different, actually. (comment <anything>)
evaluates to nil
, while the reader totally skips forms tagged with #_
. It matters sometimes.
Also, with Calva, the ”Rich Comments Forms”, that @seancorfield mentions, have special support in that all Evaluate Top Level … commands will regard comment
as creating a new top level context. So I can put the cursor anywhere within the comment
enclosed forms and execute Evaluate Top Level Form (aka defun). So it is super quick to run small experiments against my functions. (Again, I am pretty sure CIDER does similar things.). The result line comments in the above example are created using Evaluate Top Level Form (aka defun) to Comment, btw.
I also often leave some of the comment
experiments in the code. And I often thank myself later for having done so.