0
# Testing Framework
1
2
Comprehensive unit testing framework through clojure.test namespace. Clojure provides a built-in testing framework with assertions, fixtures, and test runners.
3
4
## Capabilities
5
6
### Test Definition
7
8
Core macros for defining tests and organizing test code.
9
10
```clojure { .api }
11
(deftest name & body)
12
;; Macro: defines a test function
13
;; Test function has no parameters and runs assertions
14
;; Returns: clojure.lang.Var
15
16
(testing string & body)
17
;; Macro: groups assertions with descriptive string
18
;; Provides context for test failures
19
;; Returns: result of last body expression
20
21
(with-test definition & tests)
22
;; Macro: defines function/var with embedded tests
23
;; tests are run when namespace is tested
24
;; Returns: defined var
25
```
26
27
### Assertions
28
29
Assertion macros for testing conditions and values.
30
31
```clojure { .api }
32
(is expr)
33
(is expr msg)
34
;; Macro: generic assertion - tests that expr is truthy
35
;; Optional custom failure message
36
;; Returns: expr result or throws on failure
37
38
(is (= expected actual))
39
;; Common pattern: test equality
40
(is (= expected actual) "Values should be equal")
41
42
(is (thrown? ExceptionClass expr))
43
;; Tests that expr throws specific exception type
44
(is (thrown? ArithmeticException (/ 1 0)))
45
46
(is (thrown-with-msg? ExceptionClass regex expr))
47
;; Tests exception type and message pattern
48
(is (thrown-with-msg? Exception #"divide" (/ 1 0)))
49
50
(are argv expr & args)
51
;; Macro: template for multiple similar assertions
52
;; argv: parameter vector, expr: template expression
53
;; args: argument sets to substitute
54
;; Returns: results of all instantiated expressions
55
```
56
57
### Test Execution
58
59
Functions for running tests and collecting results.
60
61
```clojure { .api }
62
(run-tests & namespaces)
63
;; Function: runs all tests in specified namespaces
64
;; If no namespaces given, runs current namespace
65
;; Returns: test result summary map
66
67
(run-all-tests)
68
(run-all-tests re)
69
;; Function: runs tests in all loaded namespaces
70
;; Optional regex to filter namespace names
71
;; Returns: test result summary map
72
73
(test-ns ns)
74
;; Function: runs all tests in specific namespace
75
;; Returns: test result summary map
76
77
(test-all-vars ns)
78
;; Function: runs all test vars in namespace
79
;; Returns: test result summary map
80
81
(test-var v)
82
;; Function: runs single test var
83
;; Returns: test result summary map
84
85
(test-vars vars)
86
;; Function: runs collection of test vars
87
;; Returns: test result summary map
88
```
89
90
### Test Results and Reporting
91
92
Functions for handling test results and customizing output.
93
94
```clojure { .api }
95
(successful? summary)
96
;; Function: returns true if test summary shows all tests passed
97
;; summary: result map from run-tests functions
98
;; Returns: boolean
99
100
(do-report m)
101
;; Function: processes test event for reporting
102
;; m: map with :type and test details
103
;; Multimethod - can be extended for custom reporting
104
;; Returns: nil
105
106
;; Test event types:
107
;; :begin-test-ns, :end-test-ns - namespace start/end
108
;; :begin-test-var, :end-test-var - test var start/end
109
;; :pass - assertion passed
110
;; :fail - assertion failed
111
;; :error - exception during test
112
;; :summary - final results
113
```
114
115
### Fixtures
116
117
Setup and teardown functions that wrap test execution.
118
119
```clojure { .api }
120
(use-fixtures fixture-type & fixtures)
121
;; Function: installs fixtures for current namespace
122
;; fixture-type: :once (per namespace) or :each (per test)
123
;; fixtures: functions that take and call a test function
124
;; Returns: nil
125
126
(compose-fixtures f1 f2)
127
;; Function: composes two fixture functions
128
;; Returns: composed fixture function
129
130
(join-fixtures fixtures)
131
;; Function: composes collection of fixtures
132
;; Returns: composed fixture function
133
```
134
135
### Test Utilities
136
137
Helper functions and variables for test development.
138
139
```clojure { .api }
140
*testing-vars*
141
;; Dynamic var: stack of vars currently being tested
142
;; Type: list of clojure.lang.Var
143
144
*testing-contexts*
145
;; Dynamic var: stack of testing context strings
146
;; Type: list of String
147
148
*test-out*
149
;; Dynamic var: PrintWriter for test output
150
;; Type: java.io.PrintWriter
151
152
(function? x)
153
;; Function: returns true if x is a function or callable
154
;; More comprehensive than fn?
155
;; Returns: boolean
156
157
(testing-vars-str m)
158
;; Function: formats current testing vars as string
159
;; Returns: String
160
161
(testing-contexts-str contexts)
162
;; Function: formats testing contexts as string
163
;; Returns: String
164
165
(inc-report-counter name)
166
;; Function: increments named counter in test results
167
;; name: :test, :pass, :fail, :error
168
;; Returns: new count
169
170
(file-position)
171
;; Function: returns current file and line info
172
;; Returns: map with :file and :line
173
```
174
175
### Custom Assertions
176
177
Building custom assertion functions and predicates.
178
179
```clojure { .api }
180
(assert-predicate msg pred expected actual)
181
;; Function: creates assertion using predicate function
182
;; Returns: actual value or reports failure
183
184
(assert-any msg expected actual)
185
;; Function: generic assertion with custom reporting
186
;; Returns: actual value or reports failure
187
188
;; Example custom assertion:
189
(defn is-even [x]
190
(is (even? x) (str x " should be even")))
191
```
192
193
**Usage Examples:**
194
195
```clojure
196
;; Basic test definition
197
(deftest simple-math-test
198
(is (= 4 (+ 2 2)))
199
(is (= 0 (- 5 5)))
200
(is (not= 4 (+ 2 3))))
201
202
;; Testing with context
203
(deftest string-operations-test
204
(testing "String concatenation"
205
(is (= "hello world" (str "hello" " " "world"))))
206
(testing "String length"
207
(is (= 5 (.length "hello"))))
208
(testing "String comparison"
209
(is (.startsWith "hello world" "hello"))))
210
211
;; Template testing with are
212
(deftest arithmetic-test
213
(are [x y expected] (= expected (+ x y))
214
1 2 3
215
0 0 0
216
-1 1 0
217
10 -5 5))
218
219
;; Exception testing
220
(deftest exception-test
221
(is (thrown? ArithmeticException (/ 1 0)))
222
(is (thrown-with-msg? NumberFormatException
223
#"For input string"
224
(Integer/parseInt "not-a-number"))))
225
226
;; Test fixtures
227
(defn database-fixture [test-fn]
228
(setup-test-database)
229
(try
230
(test-fn)
231
(finally
232
(cleanup-test-database))))
233
234
(use-fixtures :each database-fixture)
235
236
;; Multiple fixtures
237
(defn logging-fixture [test-fn]
238
(println "Starting test")
239
(test-fn)
240
(println "Finished test"))
241
242
(use-fixtures :each database-fixture logging-fixture)
243
244
;; Running tests
245
(run-tests) ; Run current namespace tests
246
(run-tests 'my.namespace) ; Run specific namespace
247
(run-all-tests) ; Run all loaded namespaces
248
(run-all-tests #"my\.project\..*") ; Run namespaces matching regex
249
250
;; Test results
251
(def results (run-tests))
252
(successful? results) ; => true/false
253
(:test results) ; Number of tests run
254
(:pass results) ; Number of assertions passed
255
(:fail results) ; Number of assertions failed
256
(:error results) ; Number of errors
257
258
;; Custom reporting
259
(defmethod do-report :fail [m]
260
(println "FAILURE in" (testing-vars-str m))
261
(when (seq *testing-contexts*)
262
(println (testing-contexts-str *testing-contexts*)))
263
(println "Expected:" (pr-str (:expected m)))
264
(println "Actual:" (pr-str (:actual m))))
265
266
;; Property-based testing pattern
267
(deftest property-test
268
(dotimes [_ 100]
269
(let [x (rand-int 1000)
270
y (rand-int 1000)]
271
(is (= (+ x y) (+ y x)) "Addition should be commutative"))))
272
273
;; Integration with fixtures
274
(defn with-temp-file [test-fn]
275
(let [temp-file (java.io.File/createTempFile "test" ".tmp")]
276
(try
277
(binding [*temp-file* temp-file]
278
(test-fn))
279
(finally
280
(.delete temp-file)))))
281
282
;; Embedded tests with with-test
283
(with-test
284
(defn multiply [x y]
285
(* x y))
286
287
(is (= 6 (multiply 2 3)))
288
(is (= 0 (multiply 0 5)))
289
(is (= -10 (multiply -2 5))))
290
```