Change IN-SUITE* to update the suite.
[fiveam.git] / t / tests.lisp
1 ;;;; -*- Mode: Lisp; indent-tabs-mode: nil -*-
2
3 (in-package :it.bese.fiveam)
4
5 (in-suite :it.bese.fiveam)
6
7 (def-suite test-suite
8     :description "Suite for tests which should fail."
9     :in nil)
10
11 (defmacro with-test-results ((results test-name) &body body)
12   `(let ((,results (with-*test-dribble* nil (run ',test-name))))
13      ,@body))
14
15 (def-fixture null-fixture ()
16   `(progn ,@(&body)))
17
18 ;;;; Test the checks
19
20 (def-test is1 (:suite test-suite)
21   (is (plusp 1))
22   (is (< 0 1))
23   (is (not (plusp -1)))
24   (is (not (< 1 0)))
25   (is-true t)
26   (is-false nil))
27
28 (def-test is2 (:suite test-suite :fixture null-fixture)
29   (is (plusp 0))
30   (is (< 0 -1))
31   (is (not (plusp 1)))
32   (is (not (< 0 1)))
33   (is-true nil)
34   (is-false t))
35
36 (def-test is (:profile t)
37   (with-test-results (results is1)
38     (is (= 6 (length results)))
39     (is (every #'test-passed-p results)))
40   (with-test-results (results is2)
41     (is (= 6 (length results)))
42     (is (every #'test-failure-p results))))
43
44 (def-test signals/finishes ()
45   (signals error
46     (error "an error"))
47   (finishes
48    (signals error
49     (error "an error"))))
50
51 (def-test pass ()
52   (pass))
53
54 (def-test fail1 (:suite test-suite)
55   (fail "This is supposed to fail"))
56
57 (def-test fail ()
58   (with-test-results (results fail1)
59     (is (= 1 (length results)))
60     (is (test-failure-p (first results)))))
61
62 ;;;; non top level checks
63
64 (def-test foo-bar ()
65   (let ((state 0))
66     (is (= 0 state))
67     (is (= 1 (incf state)))))
68
69 ;;;; Test dependencies
70
71 (def-test ok (:suite test-suite)
72   (pass))
73
74 (def-test not-ok (:suite test-suite)
75   (fail "This is supposed to fail."))
76
77 (def-test and1 (:depends-on (and ok not-ok) :suite test-suite)
78   (fail))
79
80 (def-test and2 (:depends-on (and ok) :suite test-suite)
81   (pass))
82
83 (def-test dep-and ()
84   (with-test-results (results and1)
85     (is (= 3 (length results)))
86     ;; we should have one skippedw one failed and one passed
87     (is (some #'test-passed-p results))
88     (is (some #'test-skipped-p results))
89     (is (some #'test-failure-p results)))
90   (with-test-results (results and2)
91     (is (= 2 (length results)))
92     (is (every #'test-passed-p results))))
93
94 (def-test or1 (:depends-on (or ok not-ok) :suite test-suite)
95   (pass))
96
97 (def-test or2 (:depends-on (or not-ok ok) :suite test-suite)
98   (pass))
99
100 (def-test dep-or ()
101   (with-test-results (results or1)
102     (is (= 2 (length results)))
103     (is (every #'test-passed-p results)))
104   (with-test-results (results or2)
105     (is (= 3 (length results)))
106     (is (= 2 (length (remove-if-not #'test-passed-p results))))))
107
108 (def-test not1 (:depends-on (not not-ok) :suite test-suite)
109   (pass))
110
111 (def-test not2 (:depends-on (not ok) :suite test-suite)
112   (fail))
113
114 (def-test not ()
115   (with-test-results (results not1)
116     (is (= 2 (length results)))
117     (is (some #'test-passed-p results))
118     (is (some #'test-failure-p results)))
119   (with-test-results (results not2)
120     (is (= 2 (length results)))
121     (is (some #'test-passed-p results))
122     (is (some #'test-skipped-p results))))
123
124 (def-test nested-logic (:depends-on (and ok (not not-ok) (not not-ok))
125                     :suite test-suite)
126   (pass))
127
128 (def-test dep-nested ()
129   (with-test-results (results nested-logic)
130     (is (= 3 (length results)))
131     (is (= 2 (length (remove-if-not #'test-passed-p results))))
132     (is (= 1 (length (remove-if-not #'test-failure-p results))))))
133
134 (def-test circular-0 (:depends-on (and circular-1 circular-2 or1) 
135                       :suite test-suite)
136   (fail "we depend on a circular dependency, we should not be tested."))
137
138 (def-test circular-1 (:depends-on (and circular-2)
139                       :suite test-suite)
140   (fail "we have a circular depednency, we should not be tested."))
141
142 (def-test circular-2 (:depends-on (and circular-1)
143                       :suite test-suite)
144   (fail "we have a circular depednency, we should not be tested."))
145
146 (def-test circular ()
147   (signals circular-dependency
148     (run 'circular-0))
149   (signals circular-dependency
150     (run 'circular-1))
151   (signals circular-dependency
152     (run 'circular-2)))
153
154
155 (def-suite before-test-suite :description "Suite for before test" :in nil)
156
157 (def-test before-0 (:suite before-test-suite)
158   (pass))
159
160 (def-test before-1 (:depends-on (:before before-0)
161                     :suite before-test-suite)
162   (fail))
163
164 (def-suite before-test-suite-2 :description "Suite for before test" :in nil)
165
166 (def-test before-2 (:depends-on (:before before-3)
167                     :suite before-test-suite-2)
168   (pass))
169
170 (def-test before-3 (:suite before-test-suite-2)
171   (pass))
172
173 (def-test before ()
174   (with-test-results (results before-test-suite)
175     (is (some #'test-skipped-p results)))
176   
177   (with-test-results (results before-test-suite-2)
178     (is (every #'test-passed-p results))))
179
180
181 ;;;; dependencies with symbol
182 (def-test dep-with-symbol-first (:suite test-suite)
183   (pass))
184
185 (def-test dep-with-symbol-dependencies-not-met (:depends-on (not dep-with-symbol-first)
186                                             :suite test-suite)
187   (fail "Error in the test of the test, this should not ever happen"))
188
189 (def-test dep-with-symbol-depends-on-ok (:depends-on dep-with-symbol-first :suite test-suite)
190   (pass))
191
192 (def-test dep-with-symbol-depends-on-failed-dependency (:depends-on dep-with-symbol-dependencies-not-met
193                                                     :suite test-suite)
194   (fail "No, I should not be tested becuase I depend on a test that in its turn has a failed dependecy."))
195
196 (def-test dependencies-with-symbol ()
197   (with-test-results (results dep-with-symbol-first)
198     (is (some #'test-passed-p results)))
199
200   (with-test-results (results dep-with-symbol-depends-on-ok)
201     (is (some #'test-passed-p results)))
202
203   (with-test-results (results dep-with-symbol-dependencies-not-met)
204     (is (some #'test-skipped-p results)))
205
206   ;; No failure here, because it means the test was run.
207   (with-test-results (results dep-with-symbol-depends-on-failed-dependency)
208     (is (not (some #'test-failure-p results)))))
209
210
211 ;;;; test for-all
212
213 (def-test gen-integer ()
214   (for-all ((a (gen-integer)))
215     (is (integerp a))))
216
217 (def-test for-all-guarded ()
218   (for-all ((less (gen-integer))
219             (more (gen-integer) (< less more)))
220     (is (< less more))))
221
222 (def-test gen-float ()
223   (macrolet ((test-gen-float (type)
224                `(for-all ((unbounded (gen-float :type ',type))
225                           (bounded   (gen-float :type ',type :bound 42)))
226                   (is (typep unbounded ',type))
227                   (is (typep bounded ',type))
228                   (is (<= (abs bounded) 42)))))
229     (test-gen-float single-float)
230     (test-gen-float short-float)
231     (test-gen-float double-float)
232     (test-gen-float long-float)
233
234     (for-all ((value (gen-float :type 'single-float :min 1 :max 2)))
235       (is (typep value 'single-float))
236       (is (<= (coerce 1 'single-float) value (coerce 2 'single-float))))))
237
238 (def-test gen-character ()
239   (for-all ((c (gen-character)))
240     (is (characterp c)))
241   (for-all ((c (gen-character :code (gen-integer :min 32 :max 40))))
242     (is (characterp c))
243     (member c (list #\Space #\! #\" #\# #\$ #\% #\& #\' #\())))
244
245 (def-test gen-string ()
246   (for-all ((s (gen-string)))
247     (is (stringp s)))
248   (for-all ((s (gen-string :length (gen-integer :min 0 :max 2))))
249     (is (<= (length s) 2)))
250   (for-all ((s (gen-string :elements (gen-character :code (gen-integer :min 0 :max 0))
251                            :length (constantly 2))))
252     (is (= 2 (length s)))
253     (is (every (curry #'char= #\Null) s))))
254
255 (defun dummy-mv-generator ()
256   (lambda ()
257     (list 1 1)))
258
259 (def-test for-all-destructuring-bind ()
260   (for-all (((a b) (dummy-mv-generator)))
261     (is (= 1 a))
262     (is (= 1 b))))
263
264 (def-test introspection ()
265   (is (= (length (list-all-suites))
266          (hash-table-count *suites*))))
267
268 (defvar *special-variable* nil)
269
270 (def-fixture fixture-for-suite (value)
271   (progn
272     (setf *special-variable* value)
273     (&body)))
274
275 (def-suite suite-with-fixture :fixture (fixture-for-suite 42) :in :it.bese.fiveam)
276
277 (def-test test-with-suite-fixture (:suite suite-with-fixture)
278   (is (= 42 *special-variable*)))
279
280 (def-test add-remove-test-from-suite ()
281   (let ((*test* (make-hash-table :test 'eql))
282         (*suites* (make-hash-table :test 'eql)))
283     (in-suite* empty :in nil)
284     (is (null (get-test 'foo)))
285
286     (def-test foo (:suite nil) t)
287     (is-true (get-test 'foo))
288     (is-false (gethash 'foo (tests *suite*)))
289
290     (def-test foo () t)
291     (is-true (gethash 'foo (tests *suite*)))
292
293     (def-test foo (:suite nil) t)
294     (is-false (gethash 'foo (tests *suite*)))))
295
296
297 ;;;; test suites, *suite*, in-suite* behaviour
298
299 (def-test suite-redefinition ()
300   (rem-test 'a-suite)
301   (in-suite* a-suite :description "a suite")
302   (let ((a-suite (get-test 'a-suite)))
303     (is (string= "a suite" (description a-suite)))
304
305     (in-suite* a-suite :description "the same suite")
306     (is (eq a-suite (get-test 'a-suite)))
307     (is (string= "the same suite" (description a-suite)))))