r5457: *** empty log message ***
[xlunit.git] / suite.lisp
1 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
4 ;;;;
5 ;;;; ID:      $Id: suite.lisp,v 1.6 2003/08/04 19:31:34 kevin Exp $
6 ;;;; Purpose: Suite functions for XLUnit
7 ;;;;
8 ;;;; *************************************************************************
9
10 (in-package #:xlunit)
11
12 (defclass test-suite (test)
13   ((name :initform "" :initarg :name :reader test-suite-name)
14    (tests :initarg :tests :accessor tests :initform nil)
15    (description :initarg :description :reader description
16                 :initform "No description.")))
17
18 (defmacro get-suite (class-name)
19   `(suite (make-instance ',class-name)))
20  
21
22 (defmethod add-test ((ob test-suite) (new-test test))
23   (remove-test new-test ob)
24   (setf (tests ob) (append (tests ob) (list new-test))))
25
26
27 (defmethod run-on-test-results ((ob test-suite) (result test-results)
28                                 &key (handle-errors t))
29   (mapc #'(lambda (composite)  ;;test-case or suite
30             (run-on-test-results composite result
31                                 :handle-errors handle-errors))
32         (tests ob)))
33
34 (defmethod named-test (name (suite test-suite))
35   (some (lambda (test-or-suite)
36           (when (and (typep test-or-suite 'test-case)
37                      (equal name (name test-or-suite)))
38             test-or-suite))
39         (tests suite)))
40
41 (defmethod remove-test ((test test) (suite test-suite))
42   (setf (tests suite)
43     (delete-if #'(lambda (existing-tests-or-suite)
44                    (cond ((typep existing-tests-or-suite 'test-suite)
45                           (eq existing-tests-or-suite new-test))
46                          ((typep existing-tests-or-suite 'test-case)
47                           (eql (name existing-tests-or-suite)
48                                (name test)))))
49                (tests suite))))
50
51 ;; Dynamic test suite
52
53 (defun find-test-generic-functions (instance)
54   "Return a list of symbols for generic functions specialized on the
55 class of an instance and whose name begins with the string 'test-'.
56 This is used to dynamically generate a list of tests for a fixture."
57   (let ((res)
58         (package (symbol-package (class-name (class-of instance)))))
59     (do-symbols (s package)
60       (when (and (> (length (symbol-name s)) 5)
61                  (string-equal "test-" (subseq (symbol-name s) 0 5))
62                  (fboundp s)
63                  (typep (symbol-function s) 'generic-function)
64                  (ignore-errors
65                    (plusp (length (compute-applicable-methods 
66                                    (ensure-generic-function s)
67                                    (list instance))))))
68         (push s res)))
69     (nreverse res)))
70
71
72 ;----------------------------------------------------------------------
73 ; macro def-test-method
74 ;
75 ; Creates the representation of a test method (included within a
76 ; test-case object) and add it to the corresponding suite class.
77 ; => clos version of the pluggable selector pattern
78 ;
79 ; use:  (def-test-method test-assert-false (clos-unit-test)
80 ;          (assert-true (eql (+ 1 2) 4) "comment"))
81 ;
82 ; new: it calls the textui-test-run function during eval, so to
83 ;      allow the usual lisp-like incremental developing and test.
84 ;----------------------------------------------------------------------
85                                                                                  
86 (defmacro def-test-method ((method-name instance-name class-name
87                             &key (run t))
88                            &body method-body)
89   `(let ((,instance-name
90           (make-instance ',class-name
91             :name ',method-name)))
92      (setf (method-body ,instance-name)
93            #'(lambda() ,@method-body))
94      (add-test (suite ,instance-name) ,instance-name)
95      (when ,run 
96        (textui-test-run ,instance-name))))
97