I just discovered midje, a testing library for clojure. Clojure already comes with clojure.test and it looks something like this:

(ns tic-tac-toe.core-test
  (:require [clojure.test :refer :all]
            [tic-tac-toe.core :refer :all]))

(deftest init-position-test
  (let [position (init-position)
        ply (:ply position)]
    (testing "initialize a board."
      (is (= (:board position) '[- - -, - - -, - - -])))
    (testing "make sure it is x's turn"
      (is (= (:turn position) 'x)))))

An error looks like this

euler:tic-tac-toe.clj ckim$ lein test

lein test tic-tac-toe.core-test

lein test :only tic-tac-toe.core-test/position-string-test

FAIL in (position-string-test) (core_test.clj:15)
display of position
expected: (= (position-str (init-position)) "   |   |   \\n-----------\\n   |   |   \\n-----------\\n   |   |   ")
  actual: (not (= " 0 | 1 | 2 \\n-----------\\n 3 | 4 | 5 \\n-----------\\n 6 | 7 | 8 " "   |   |   \\n-----------\\n   |   |   \\n-----------\\n   |   |   "))

Ran 8 tests containing 22 assertions.
1 failures, 0 errors.
Tests failed.

If you fix the problem it, will look like this:

euler:tic-tac-toe.clj ckim$ lein test

lein test tic-tac-toe.core-test

Ran 8 tests containing 22 assertions.
0 failures, 0 errors.

With midje, it looks like

(ns ttt.midje
  (:use [midje.sweet]))

(fact (+ 2 2) => 5)
(fact (+ 2 2) => odd?)

Error output looks like

euler:ttt ckim$ lein midje

FAIL at (midje.clj:4)
    Expected: 5
      Actual: 4

FAIL at (midje.clj:5)
Actual result did not agree with the checking function.
        Actual result: 4
    Checking function: odd?

If you correct it, it looks like

euler:ttt ckim$ lein midje
All checks (2) succeeded.

To get midje set up, you need to add this to ~/.lein/profiles.clj

{:user {:plugins [[lein-midje "3.0.0"]]}}

Add this to project.clj in your project root directory

  :profiles  {:dev  {:dependencies  [[midje "1.5.0"]]}}

Then you run the following to fetch the necessary files.

$ lein deps

Once you have it set up, you can modify the file located in test/<app>/midje.clj directory (test/ttt/midje.clj).

To get stubbing, you pass (provided <function-call> => <result>). For example, assume foo calls bar, you can define:

(fact
  (foo) => 'hello
  (provided (bar) => 'hello))