clojure.test Testing Framework
Qualified supports clojure.test, the built-in testing framework for Clojure 1.6.0
The following notes are largely derived from: clojure.test - Clojure API Documentation.
A minimal test fixture looks as follows:
- Solution Code:
(ns clojure.greeter) (defn make-greeter [greeter-name] (fn [your-name] (format "My name is %s! Welcome, %s!" greeter-name your-name)))
- Test Fixture
(ns clojure.greeter-test (:require [clojure.test :refer :all] [clojure.greeter :refer :all])) (deftest Greetings (is (= ((make-greeter "Shoki, the Demon Queller") "Son Gokū, the Monkey King") "My name is Shoki, the Demon Queller! Welcome, Son Gokū, the Monkey King!")))
The core of the
clojure.test library is the
is macro, which lets you make assertions of any arbitrary expression:
(is (= 4 (+ 2 2))) (is (instance? Integer 256)) (is (.startsWith "abcde" "ab"))
These are all passing tests. They are all expected to output:
The following test won't pass, however:
(deftest Will-Fail (is (= 5 (+ 2 2))))
It will output:
Will-Fail expected: (= 5 (+ 2 2)) - actual: (not (= 5 4))
expected: line shows you the original expression, and the
actual: shows you what actually happened. In this case, it shows that
(+ 2 2) returned
4, which is not
There are two special assertions for testing exceptions. The
(is (thrown? c ...)) form tests if an exception of class
c is thrown:
(is (thrown? ArithmeticException (/ 1 0)))
(is (thrown-with-msg? c re ...)) does the same thing and also tests that the message on the exception matches the regular expression
(is (thrown-with-msg? ArithmeticException #"Divide by zero" (/ 1 0)))
is takes an optional second argument, a string describing the assertion. This message will be included in the error report.
(is (= 5 (+ 2 2)) "Crazy arithmetic")
In addition, you can document groups of assertions with the "testing" macro, which takes a string followed by any number of assertions. The string will be included in failure reports. Calls to "testing" may be nested, and all of the strings will be joined together with spaces in the final report, in a style similar to RSpec.
(testing "Arithmetic" (testing "with positive integers" (is (= 4 (+ 2 2))) (is (= 7 (+ 3 4)))) (testing "with negative integers" (is (= -4 (+ -2 -2))) (is (= -1 (+ 3 -4)))))
Note that, unlike RSpec, the
testing macro may only be used INSIDE a
(are argv expr & args)
Checks multiple assertions with a template expression.
See clojure.template/do-template for an explanation of templates.
(are [x y] (= x y) 2 (+ 1 1) 4 (* 2 2))
(do (is (= 2 (+ 1 1))) (is (= 4 (* 2 2))))
Note: This breaks some reporting features, such as line numbers.
One of the most powerful tools of testing in clojure is the
with-redefs macro, which allows you to mock functions.
This is especially useful when you want to prevent access to built-ins for some exercise. For example, the following disables
(with-redefs [clojure.core/reverse (fn [& _] (throw (Exception. "Sorry! The reverse built-in is disabled for this challenge!")))] (deftest Reversing (is (= (reverse ) ))))
We should expect this test to fail, since it is clearly is using