1 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
5 ;;;; ID: $Id: suite.lisp,v 1.2 2003/08/04 12:16:13 kevin Exp $
6 ;;;; Purpose: Suite functions for XLUnit
8 ;;;; *************************************************************************
12 (defclass test-suite ()
13 ((name :initarg :name :reader test-suite-name)
14 (tests :initarg :tests :accessor tests-hash
15 :initform (make-hash-table :test 'equal))
16 (description :initarg :description :reader description
17 :initform "No description.")))
20 (defmethod setup-testsuite-named (name)
21 (declare (ignore name))
24 (defmethod teardown-testsuite-named (name)
25 (declare (ignore name))
28 (defmethod run-test ((suite test-suite)
29 &key (result (make-instance 'test-result))
31 (setup-testsuite-named (slot-value suite 'name))
32 (dolist (test (tests suite))
33 (run-test test :result result :handle-errors handle-errors))
34 (teardown-testsuite-named (slot-value suite 'name))
37 (defmethod tests ((suite test-suite))
39 (maphash #'(lambda (k v)
41 (setf tlist (cons v tlist)))
46 (defun make-test-suite (name-or-fixture &optional description testspecs)
47 "Returns a new test-suite based on a name and TESTSPECS or a fixture
49 (etypecase name-or-fixture
51 (make-test-suite-for-fixture (make-instance name-or-fixture)))
53 (let ((suite (make-instance 'test-suite :name name-or-fixture
54 :description description)))
55 (dolist (testspec testspecs)
56 (add-test (apply #'make-test testspec) suite))
60 (defmethod add-test ((test test-fixture) (suite test-suite))
61 (setf (gethash (test-name test) (tests-hash suite)) test))
63 (defmethod add-test ((test test-suite) (suite test-suite))
64 (setf (gethash (test-suite-name test) (tests-hash suite)) test))
66 (defmethod remove-test ((test test-fixture) (suite test-suite))
67 (remhash (test-name test) (tests-hash suite)))
69 (defmethod remove-test ((test test-suite) (suite test-suite))
70 (remhash (test-suite-name test) (tests-hash suite)))
72 (defmethod test-named ((name string) (suite test-suite))
73 (gethash name (tests-hash suite)))
78 (defun make-test-suite-for-fixture
81 (format nil "Automatic for ~A"
82 (if (slot-boundp fixture 'test-name)
86 (let ((suite (make-instance 'test-suite
88 :description description))
89 (fns (find-test-generic-functions fixture)))
91 (make-test (class-name (class-of fixture)) fn
95 (defun find-test-generic-functions (instance)
96 "Return a list of symbols for generic functions specialized on the
97 class of an instance and whose name begins with the string 'test-'.
98 This is used to dynamically generate a list of tests for a fixture."
100 (package (symbol-package (class-name (class-of instance)))))
101 (do-symbols (s package)
102 (when (and (> (length (symbol-name s)) 5)
103 (string-equal "test-" (subseq (symbol-name s) 0 5))
105 (typep (symbol-function s) 'generic-function)
106 (plusp (length (compute-applicable-methods
107 (ensure-generic-function s)
115 (defmethod text-testrunner ((suite test-suite) &key (stream t)
117 (let* ((start-time (get-internal-real-time))
118 (result (run-test suite :handle-errors handle-errors))
119 (seconds (/ (- (get-internal-real-time) start-time)
120 internal-time-units-per-second)))
121 (result-printer result seconds stream)))