2 ;;;; xptest-eaxmple.lisp --- Example of test suite based on Extreme
3 ;;;; Programming Framework by Kent Beck
5 ;;;; Author: Craig Brozefsky <craig@onshore.com>
6 ;;;; Put in public domain by onShore, Inc
7 (in-package :xp-test-example)
9 ;;; First we define some basic fixtures that we are going to need to
10 ;;; perform our tests. A fixture is a place to hold data we need
11 ;;; during testing. Often there are many test cases that use the same
12 ;;; data. Each of these test cases is an instance of a test-fixture.
14 (def-test-fixture math-fixture ()
19 (:documentation "Test fixture for math testing"))
21 ;;; Then we define a setup method for the fixture. This method is run
22 ;;; prior to perfoming any test with an instance of this fixture. It
23 ;;; should perform all initialization needed, and assume that it is starting
24 ;;; with a pristine environment, well to a point, use your head here.
26 (defmethod setup ((fix math-fixture))
27 (setf (numbera fix) 2)
28 (setf (numberb fix) 3))
30 ;;; Then we define a teardown method, which should return the instance
31 ;;; to it's original form and reset the environment. In this case
32 ;;; there is little for us to do since the fixture is quite static.
33 ;;; In other cases we may need to clear some database tables, or
34 ;;; otherwise get rid of state built up while perofmring the test.
35 ;;; Here we just return T.
37 (defmethod teardown ((fix math-fixture))
40 ;;; Once we hav a fixture we can start defining method on it which
41 ;;; will perform tests. These methods should take one argument, an
42 ;;; instance of the fixture. The method performs some operation and
43 ;;; then performs some tests to determine if the proper behavior
44 ;;; occured. If there is a failure to behave as excpeted the method
45 ;;; raises a test-failure object by calling the method FAILURE. This
46 ;;; is much like calling ERROR in that it stops processing that
47 ;;; method. Each method should only check for one aspect of behavior.
48 ;;; This way triggering one failure would not result in another
49 ;;; behavior check from being skipped. It does not matter what these
52 (defmethod addition-test ((test math-fixture))
53 (let ((result (+ (numbera test) (numberb test))))
55 (failure "Result was not 5 when adding ~A and ~A"
56 (numbera test) (numberb test)))))
58 (defmethod subtraction-test ((test math-fixture))
59 (let ((result (- (numberb test) (numbera test))))
61 (failure "Result was not 1 when subtracting ~A ~A"
62 (numberb test) (numbera test)))))
64 ;;; This method is meant to signal a failure
65 (defmethod subtraction-test2 ((test math-fixture))
66 (let ((result (- (numbera test) (numberb test))))
68 (failure "Result was not 1 when subtracting ~A ~A"
69 (numbera test) (numberb test)))))
72 ;;; Now we can create a test-suite. A test-suite contains a group of
73 ;;; test-cases (instances of test-fixture) and/or other test-suites.
74 ;;; We can specify which tests are in a test-suite when we define the
75 ;;; test-suite, or we can add them later. See the documentation and
76 ;;; argument list for make-test-case for details on how to specify a
79 (setf math-test-suite (make-test-suite
81 "Simple test suite for arithmetic operators."
82 ("Addition Test" 'math-fixture
83 :test-thunk 'addition-test
84 :description "A simple test of the + operator")
85 ("Subtraction Test" 'math-fixture
86 :test-thunk 'subtraction-test
87 :description "A simple test of the - operator")))
89 (add-test (make-test-case "Substraction Test 2" 'math-fixture
90 :test-thunk 'subtraction-test2
91 :description "A broken substraction test, should fail.")
94 ;;;; Finally we can run our test suite and see how it performs.
95 ;;;; (report-result (run-test math-test-suite) :verbose t)