(defparameter *tests* nil) (defstruct example in out about (failp nil)) (defun eg (in &key (of "example") (out 'any)) (make-example :about of :in in :out out)) (defun egs (key &rest l) (if (cdr (assoc key *tests*)) (setf (cdr (assoc key *tests*)) l) (push (cons key l) *tests*)) key) (defun eg0 (key &optional (all-tests *tests*)) (cdr (assoc key all-tests))) (defun demo (key &optional (s t) (all-tests *tests*)) "(demo key) ;; run tests from key, output to screen. (demo key nil) ;; run tests from key, suppress output return number of failed tests" (let ((n 0) (failed 0) (all (eg0 key all-tests))) (dolist (x all failed) (incf n) (format s "~%;;;; ~a) ~a~%;IN: ~a~%" n (example-about x) (example-in x)) (let* ((want (example-out x)) (got (eval (example-in x))) (happy (or (equalp want 'any) (equalp got want)))) (if (example-failp x) (setf happy (not happy))) (format s ";GOT: ~a~%" got) (cond (happy (format s ";ok~%")) (t (format s ";WANT: ~a~%;BAD !!!!!!!!!!!!!!!!!!!~%" want) (incf failed))))))) (defun demof (key file) (with-open-file (*standard-output* file :direction :output :if-exists :supersede) (let ((n (demo key))) (format t "~%;failures = ~a~%" n)))) ;;;; (egs :demo (eg '(+ 1 2) :of "define an example" :out 3) (eg '(+ 2 3) :of "define an example with any output") (eg '(+ 10 20) :of "define a failing example" :out 0) (eg '(+ 2 3)) (eg '(+ 7 3)) )