`clojure.test` is the testing framework included with Clojure. It defines tests, checks expectations, groups related assertions, runs tests by var or namespace, and reports failures. Tests are attached to vars through metadata. The framework also supports fixtures and extensible assertions and reporting. section 22.9
The main tools serve different parts of a test:
- `deftest` defines a test in the current namespace; `deftest-` makes it nonpublic. `with-test` defines a function and its test together. section 22.9
- `is` checks a truthy expression and reports what failed; an optional message adds context. `testing` labels nested contexts, while `are` applies one assertion pattern to multiple input rows. section 22.9
- `test-var` runs one test var. `run-tests` runs tests in a namespace and returns counts for tests, passes, failures and errors. `run-all-tests` can select namespaces with a regular expression. section 22.9
A failing numerical expectation
`(deftest sqrt-test (is (= 2 (sqrt 4)) "Expecting 2"))` defines a check; `(test-var #'sqrt-test)` runs it. The shown Newton-method `sqrt` returns `2.000000000000002` for `4`, so exact equality fails. The report includes the message, expected expression and actual result. This is a useful signal to choose an expectation suited to approximate computation. section 22.9
Assertions can also check exceptions with `thrown?` or `thrown-with-msg?`. A check that raises an unexpected exception is reported as an error rather than an ordinary failed expectation. For reusable numerical checks, `assert-expr` can extend `is` with a custom assertion and report. section 22.9
(require '[clojure.test :refer [is deftest] :as t]) (defmethod t/assert-expr 'roughly [msg form] ; #1 `(let [op1# ~(nth form 1) ; #2 op2# ~(nth form 2) tolerance# (if (= 4 ~(count form)) ~(last form) 2) decimals# (/ 1. (Math/pow 10 tolerance#)) result# (< (Math/abs (- op1# op2#)) decimals#)] (t/do-report ; #3 {:type (if result# :pass :fail) :message ~msg :expected (format "%s should be roughly %s with %s tolerance" op1# op2# decimals#) :actual result#}) result#)) (deftest sqrt-test ; #4 (is (roughly 2 (sqrt 4) 14)) (is (roughly 2 (sqrt 4) 15))) (t/test-var #'sqrt-test) ;; FAIL in (sqrt-test) (form-init205.clj:3) ;; expected: "2 should be roughly 2.000000000000002 with 1.0E-15 tolerance" ;; actual: false
This `assert-expr` method adds a `roughly` assertion with a selectable tolerance. Its two square-root checks show how a stricter tolerance can turn a pass into a reported failure. section 22.9
A namespace can control which tests `test-ns` runs by defining `test-ns-hook`. Fixtures wrap test execution for setup and teardown; with `use-fixtures :each`, the wrapper runs around every test. These mechanisms help compose a suite without putting setup steps into each assertion. section 22.9
