;;; -*- mode: Lisp; Syntax: Common-Lisp; -*- ;;; ;;; Copyright (c) 2006 by the authors. ;;; ;;; See LICENCE for details. (in-package :stefil) #.(file-header) (defmacro defsuite (name-or-name-with-args &optional args &body body) (bind (((name &rest deftest-args) (ensure-list name-or-name-with-args))) (with-unique-names (test) `(progn (deftest (,name ,@deftest-args) ,args (bind ((,test (find-test ',name))) (flet ((run-child-tests () (iter (for (nil subtest) :in-hashtable (children-of ,test)) (when (and (auto-call-p subtest) (or (zerop (length (lambda-list-of subtest))) (member (first (lambda-list-of subtest)) '(&key &optional)))) (funcall (name-of subtest)))))) ,@(or body `((if (test-was-run-p ,test) (warn "Skipped executing already run tests suite ~S" (name-of ,test)) (run-child-tests)))))) (values)) (values (find-test ',name)))))) (defmacro defsuite* (name-or-name-with-args &optional args &body body) "Equivalent to (in-suite (defsuite ...)) which is the preferred way to define suites." `(in-suite (defsuite ,name-or-name-with-args ,args ,@body))) (setf *root-suite* (make-suite 'root-suite :documentation "Root Suite")) (setf *suite* *root-suite*) (defmacro in-root-suite () "Used to reset the current suite to protect from other project's last in-suite statement. Unfortunately there's noone for us to rebind *suite* when a file is loaded, so we can't behave exactly like *package* and in-package." `(setf *suite* *root-suite*)) (defmacro in-suite (name) `(setf *suite* ,(if (symbolp name) `(find-test ',name :otherwise (lambda () (cerror "Create a new suite named ~A." "Unkown suite ~A." ',name) (defsuite ,name))) name)))