be9e113565a7ad9b46a4781b8ee274b4cf40d5be
[fiveam.git] / t / example.lisp
1 ;; -*- lisp -*-
2
3 ;;;; * FiveAM Example (poor man's tutorial)
4
5 (asdf:oos 'asdf:load-op :fiveam)
6
7 (defpackage :it.bese.fiveam.example
8   (:use :common-lisp
9         :it.bese.fiveam))
10
11 (in-package :it.bese.fiveam.example)
12
13 ;;;; First we need some functions to test.
14
15 (defun add-2 (n)
16   (+ n 2))
17
18 (defun add-4 (n) 
19   (+ n 4))
20
21 ;;;; Now we need to create a test which makes sure that add-2 and add-4
22 ;;;; work as specified.
23
24 ;;;; we create a test named ADD-2 and supply a short description.
25 (test add-2
26  "Test the ADD-2 function" ;; a short description
27  ;; the checks
28  (is (= 2 (add-2 0)))
29  (is (= 0 (add-2 -2))))
30
31 ;;;; we can already run add-2. This will return the list of test
32 ;;;; results, it should be a list of two test-passed objects.
33
34 (run 'add-2) 
35
36 ;;;; since we'd like to have some kind of readbale output we'll explain
37 ;;;; the results
38
39 (explain! (run 'add-2))
40
41 ;;;; or we could do both at once:
42
43 (run! 'add-2)
44
45 ;;;; So now we've defined and run a single test. Since we plan on
46 ;;;; having more than one test and we'd like to run them together let's
47 ;;;; create a simple test suite.
48
49 (def-suite example-suite :description "The example test suite.")
50
51 ;;;; we could explictly specify that every test we create is in the the
52 ;;;; example-suite suite, but it's easier to just change the default
53 ;;;; suite:
54
55 (in-suite example-suite)
56
57 ;;;; now we'll create a new test for the add-4 function.
58
59 (test add-4
60   (is (= 0 (add-4 -4))))
61
62 ;;;; now let's run the test
63
64 (run! 'add-4)
65
66 ;;;; we can get the same effect by running the suite:
67
68 (run! 'example-suite)
69
70 ;;;; since we'd like both add-2 and add-4 to be in the same suite, let's
71 ;;;; redefine add-2 to be in this suite:
72
73 (test add-2 "Test the ADD-2 function"
74  (is (= 2 (add-2 0)))
75  (is (= 0 (add-2 -2))))
76
77 ;;;; now we can run the suite and we'll see that both add-2 and add-4
78 ;;;; have been run (we know this since we no get 4 checks as opposed to
79 ;;;; 2 as before.
80
81 (run! 'example-suite)
82
83 ;;;; Just for fun let's see what happens when a test fails. Again we'll
84 ;;;; redefine add-2, but add in a third, failing, check:
85
86 (test add-2 "Test the ADD-2 function"
87  (is (= 2 (add-2 0)))
88  (is (= 0 (add-2 -2)))
89  (is (= 0 (add-2 0))))
90
91 ;;;; Finally let's try out the specification based testing.
92
93 (defun dummy-add (a b)
94   (+ a b))
95
96 (defun dummy-strcat (a b)
97   (concatenate 'string a b))
98
99 (test dummy-add
100   (for-all ((a (gen-integer))
101             (b (gen-integer)))
102     ;; assuming we have an "oracle" to compare our function results to
103     ;; we can use it:
104     (is (= (+ a b) (dummy-add a b)))
105     ;; if we don't have an oracle (as in most cases) we just ensure
106     ;; that certain properties hold:
107     (is (= (dummy-add a b)
108            (dummy-add b a)))
109     (is (= a (dummy-add a 0)))
110     (is (= 0 (dummy-add a (- a))))
111     (is (< a (dummy-add a 1)))
112     (is (= (* 2 a) (dummy-add a a)))))
113
114 (test dummy-strcat
115   (for-all ((result (gen-string))
116             (split-point (gen-integer :min 0 :max 10000)
117                          (< split-point (length result))))
118     (is (string= result (dummy-strcat (subseq result 0 split-point)
119                                       (subseq result split-point))))))
120
121 (test random-failure
122   (for-all ((result (gen-integer :min 0 :max 1)))
123     (is (plusp result))
124     (is (= result 0))))
125
126 (run! 'example-suite)