(ns clojure.test.example

(:use clojure.test))



(run-all-tests)

Testing clojure.walk



Testing clojure.core



(a bunch of other namespaces tested)



Testing clojure.zip



Ran 0 tests containing 0 assertions.

0 failures, 0 errors.

(run-all-tests)

(deftest add-1-to-1

(is (= 2 (+ 1 1))))

Testing clojure.walk



Testing clojure.test.example



(a bunch of other namespaces tested)



Ran 1 tests containing 1 assertions.

0 failures, 0 errors.

clojure.test.example

(defn add [x y] (+ x y))



(deftest add-x-to-y

(is (= 5 (add 2 3))))

Ran 2 tests containing 2 assertions.

0 failures, 0 errors.

(deftest add-x-to-y-a-few-times

(is (= 5 (add 2 3)))

(is (= 5 (add 1 4)))

(is (= 5 (add 3 2))))

Ran 3 tests containing 5 assertions.

0 failures, 0 errors.

clojure.test

are

are

(deftest add-x-to-y-a-using-are

(are [x y] (= 5 (add x y))

2 3

1 4

3 2))

Ran 4 tests containing 8 assertions.

are

(deftest grab-map-values-using-are

(are [y z] (= y (:x z))

2 {:x 2}

1 {:x 1}

3 {:x 3 :y 4}))

Ran 5 tests containing 11 assertions.

is

are

run-all-tests

(run-all-tests #"clojure.test.example")



Testing clojure.test.example



Ran 5 tests containing 11 assertions.

0 failures, 0 errors.

(defmethod report :begin-test-ns [m]

(with-test-out

(when (some #(:test (meta %)) (vals (ns-interns (:ns m))))

(println "

Testing" (ns-name (:ns m))))))

run-all-tests

(.addShutdownHook

(Runtime/getRuntime)

(proxy [Thread] []

(run []

(run-all-tests))))

(ns test-helper

(:use clojure.test))



(defmethod report :begin-test-ns [m]

(with-test-out

(if (some #(:test (meta %)) (vals (ns-interns (:ns m))))

(println "

Testing" (ns-name (:ns m))))))



(.addShutdownHook

(Runtime/getRuntime)

(proxy [Thread] []

(run []

(run-all-tests))))

use

use

(ns clojure.test.example

(:use clojure.test test-helper))



(deftest add-1-to-1

(is (= 2 (+ 1 1))))



(defn add [x y] (+ x y))



(deftest add-x-to-y

(is (= 5 (add 2 3))))



(deftest add-x-to-y-a-few-times

(is (= 5 (add 2 3)))

(is (= 5 (add 1 4)))

(is (= 5 (add 3 2))))



(deftest add-x-to-y-a-using-are

(are [x y] (= 5 (add x y))

2 3

1 4

3 2))



(deftest grab-map-values-using-are

(are [y z] (= y (:x z))

2 {:x 2}

1 {:x 1}

3 {:x 3 :y 4}))

(ns test-helper

(:use clojure.test))



(defmethod report :begin-test-ns [m]

(with-test-out

(if (some #(:test (meta %)) (vals (ns-interns (:ns m))))

(println "

Testing" (ns-name (:ns m))))))



(.addShutdownHook

(Runtime/getRuntime)

(proxy [Thread] []

(run []

(run-all-tests))))

I'll admit it, the first thing I like to do when learning a new language is fire up a REPL . However, I'm usually ready for the next step after typing in a few numbers, strings and defining a function or two.What feels like centuries ago, Mike Clark wrote an article about using unit testing to learn a new language. Mike was ahead of his time. This blog entry should help you if you want to follow Mike's advice.Luckily, Clojure has built in support for simple testing. (I'm currently using Clojure 1.2, you can download it from clojure.org Before we get started, let's make sure everything is working. Save a file with the following clojure in it and run* it with clojure.If everything is okay, you should see something similar the following output.If you've gotten this far, you are all set to start writing your own tests. If you are having any trouble, I suggest logging into the #clojure IRC chat room on Freenode.netThe syntax for defining tests is very simple. The following test verifies that 1 + 1 = 2. You'll want to add the test after the ns definition and before thein the file you just created.Running the test should produce something similar to the following output.We see all of the standard clojure namespaces; however, we see our namespace () in the results as well. The output at the bottom also tells us that 1 test with 1 assertion was executed.The following example shows testing a custom add function. (we will add additional tests from here, without ever deleting the old tests)If everything goes to plan, running your tests should now produce the following text towards the bottom of the output.At this point you might want to pass in a few different numbers to verify that add works as expected.Running the tests shows us our statusThis works perfectly fine; however,also providesfor verifying several values.The following example tests the same conditions usingAnd, the unsurprising results.That's a simple; however, you can do whatever you need in the form. Let's grab the value out of a map as an additional example.Leaving us withTheand macros will be all that you need for 90% of all the tests you'll ever want to write. For additional assertions and more details you can check out the clojure.test documentation.Advanced Topics (very unnecessary to get started)I get annoyed with noise in my test results. Our results have been very noisy due to the namespace reporting. Thefunction takes a regular expression ( documented here ). We can change our test running call to include a regular expression, as the following example shows.Once we switch to providing a regular expression the results should be limited to the following output.This approach works fine for our current sample file; however, it seems like a better solution would be to stop reporting namespaces that do not contain any tests. The following snippet changes the report multimethod to ignore namespaces that don't contain any tests.If you're just getting started, don't worry you don't need to understand what's going on in that snippet. I've copied the original report method and made it conditional by adding the code in bold. As a result, the namespace is only printed if it contains any tests.Now that our results are clean, let's talk about ways of getting those results.Adding calls to thefunction isn't a big deal when working with one namespace; however, you'll need to get clever when you want to run a suite of tests. I've been told that leiningen and Maven have tasks that allow you to run all the tests. You might want to start there. I don't currently use either one, and I'm lazy. I don't want to set up either, especially since all I want to do is run all my tests.It turns out it's very easy to add a shutdown hook in Java. So, as a simple solution, I run all my tests from the Java shutdown hook.In general, I create a test_helper.clj with the following code.Once you've created a test_helper.clj you cantest-helper (just like youd clojure.test) (example below) and your tests will automatically be run on exit, and only namespaces with tests will be included in the output.It's worth noting that some clojure.contrib namespaces seem to include tests, so in practice I end up using a regular expression that ignores all namespaces beginning with "clojure"** when running all tests. With all of those ideas combined, I find I can execute all my tests or only the tests in the current namespace very easily.Below you can find all the code from this entry.clojure.test.example.cljtest_helper.clj* Running a clojure file should be as easy as: java -cp /path/to/clojure.jar clojure.main -i file.to.run.clj** (run-all-tests #"[^(clojure)].*") ; careful though, now your clojure.test.example tests will be ignored. Don't let that confuse you.