;;;; *************************************************************************
;;;; FILE IDENTIFICATION
;;;;
-;;;; ID: $Id: suite.lisp,v 1.2 2003/08/04 12:16:13 kevin Exp $
+;;;; ID: $Id: suite.lisp,v 1.3 2003/08/04 16:13:58 kevin Exp $
;;;; Purpose: Suite functions for XLUnit
;;;;
;;;; *************************************************************************
(in-package #:xlunit)
(defclass test-suite ()
- ((name :initarg :name :reader test-suite-name)
- (tests :initarg :tests :accessor tests-hash
- :initform (make-hash-table :test 'equal))
+ ((name :initform "" :initarg :name :reader test-suite-name)
+ (tests :initarg :tests :accessor tests :initform nil)
(description :initarg :description :reader description
:initform "No description.")))
+(defmacro get-suite (class-name)
+ `(suite (make-instance ',class-name)))
+
(defmethod setup-testsuite-named (name)
(declare (ignore name))
(declare (ignore name))
t)
-(defmethod run-test ((suite test-suite)
+(defmethod run-on-test ((suite test-suite)
&key (result (make-instance 'test-result))
(handle-errors t))
(setup-testsuite-named (slot-value suite 'name))
(dolist (test (tests suite))
- (run-test test :result result :handle-errors handle-errors))
+ (run-on-test test :result result :handle-errors handle-errors))
(teardown-testsuite-named (slot-value suite 'name))
result)
-(defmethod tests ((suite test-suite))
- (let ((tlist nil))
- (maphash #'(lambda (k v)
- (declare (ignore k))
- (setf tlist (cons v tlist)))
- (tests-hash suite))
- (reverse tlist)))
+(defmethod add-test ((ob test-suite) (new-test test))
+ (setf (tests ob)
+ (delete-if #'(lambda (existing-tests-or-suite)
+ (cond ((typep existing-tests-or-suite 'test-suite)
+ (eq existing-tests-or-suite new-test))
+ ((typep existing-tests-or-suite 'test-case)
+ (eql (name existing-tests-or-suite)
+ (name new-test)))))
+ (tests ob)))
+ (setf (tests ob) (append (tests ob) (list new-test))))
-(defun make-test-suite (name-or-fixture &optional description testspecs)
- "Returns a new test-suite based on a name and TESTSPECS or a fixture
-instance"
- (etypecase name-or-fixture
- (symbol
- (make-test-suite-for-fixture (make-instance name-or-fixture)))
- (string
- (let ((suite (make-instance 'test-suite :name name-or-fixture
- :description description)))
- (dolist (testspec testspecs)
- (add-test (apply #'make-test testspec) suite))
- suite))))
-
-
-(defmethod add-test ((test test-fixture) (suite test-suite))
- (setf (gethash (test-name test) (tests-hash suite)) test))
-
-(defmethod add-test ((test test-suite) (suite test-suite))
- (setf (gethash (test-suite-name test) (tests-hash suite)) test))
-
-(defmethod remove-test ((test test-fixture) (suite test-suite))
- (remhash (test-name test) (tests-hash suite)))
+#|
+(defmethod remove-test ((test test-case) (suite test-suite))
+ (remhash (name test) (tests-hash suite)))
(defmethod remove-test ((test test-suite) (suite test-suite))
(remhash (test-suite-name test) (tests-hash suite)))
-(defmethod test-named ((name string) (suite test-suite))
+(defmethod named ((name string) (suite test-suite))
(gethash name (tests-hash suite)))
-
+|#
;; Dynamic test suite
(fixture &key
(name
(format nil "Automatic for ~A"
- (if (slot-boundp fixture 'test-name)
- (test-name fixture)
+ (if (slot-boundp fixture 'name)
+ (name fixture)
(type-of fixture))))
description)
(let ((suite (make-instance 'test-suite
(string-equal "test-" (subseq (symbol-name s) 0 5))
(fboundp s)
(typep (symbol-function s) 'generic-function)
- (plusp (length (compute-applicable-methods
- (ensure-generic-function s)
- (list instance)))))
+ (ignore-errors
+ (plusp (length (compute-applicable-methods
+ (ensure-generic-function s)
+ (list instance))))))
(push s res)))
(nreverse res)))
+;----------------------------------------------------------------------
+; macro def-test-method
+;
+; Creates the representation of a test method (included within a
+; test-case object) and add it to the corresponding suite class.
+; => clos version of the pluggable selector pattern
+;
+; use: (def-test-method test-assert-false (clos-unit-test)
+; (assert-true (eql (+ 1 2) 4) "comment"))
+;
+; new: it calls the textui-test-run function during eval, so to
+; allow the usual lisp-like incremental developing and test.
+;----------------------------------------------------------------------
+
+(defmacro def-test-method (method-name class-name &body method-body)
+ `(let ((,(caar class-name)
+ (make-instance ',(cadar class-name)
+ :name ',method-name)))
+ (setf (method-body ,(caar class-name))
+ #'(lambda() ,@method-body))
+ (add-test (suite ,(caar class-name)) ,(caar class-name))
+ (textui-test-run ,(caar class-name))))
+
+
;;; Test Runners
-(defmethod text-testrunner ((suite test-suite) &key (stream t)
+(defmethod textui-test-run ((suite test-suite) &key (stream t)
(handle-errors t))
(let* ((start-time (get-internal-real-time))
- (result (run-test suite :handle-errors handle-errors))
+ (result (run-on-test suite :handle-errors handle-errors))
(seconds (/ (- (get-internal-real-time) start-time)
internal-time-units-per-second)))
(result-printer result seconds stream)))