Rebind a copy of *readtable* before running a test
[fiveam.git] / src / run.lisp
index 54a9020..59e6455 100644 (file)
@@ -36,6 +36,9 @@
 (defparameter *debug-on-error* nil
   "T if we should drop into a debugger on error, NIL otherwise.")
 
+(defparameter *debug-on-failure* nil
+  "T if we should drop into a debugger on a failing check, NIL otherwise.")
+
 (defun import-testing-symbols (package-designator)
   (import '(5am::is 5am::is-true 5am::is-false 5am::signals 5am::finishes)
          package-designator))
@@ -125,27 +128,34 @@ run."))
   (with-run-state (result-list)
     (bind-run-state ((current-test test))
       (labels ((abort-test (e)
-                 (add-result  'unexpected-test-failure
-                              :test-expr nil
-                              :test-case test
-                              :reason (format nil "Unexpected Error: ~S." e)
-                              :condition e))
+                 (add-result 'unexpected-test-failure
+                             :test-expr nil
+                             :test-case test
+                             :reason (format nil "Unexpected Error: ~S~%~A." e e)
+                             :condition e))
                (run-it ()
                  (let ((result-list '()))
                    (declare (special result-list))
-                   (handler-bind ((error (lambda (e)
-                                           (unless *debug-on-error*
+                   (handler-bind ((check-failure (lambda (e)
+                                                   (declare (ignore e))
+                                                   (unless *debug-on-failure*
+                                                     (invoke-restart
+                                                      (find-restart 'ignore-failure)))))
+                                  (error (lambda (e)
+                                           (unless (or *debug-on-error*
+                                                       (typep e 'check-failure))
                                              (abort-test e)
                                              (return-from run-it result-list)))))
                      (restart-case
-                         (funcall (test-lambda test))
+                         (let ((*readtable* (copy-readtable)))
+                           (funcall (test-lambda test)))
                        (retest ()
                          :report (lambda (stream)
                                    (format stream "~@<Rerun the test ~S~@:>" test))
                          (return-from run-it (run-it)))
                        (ignore ()
                          :report (lambda (stream)
-                                   (format stream "~@<Signal a test failure and abort the test ~S.~@:>" test))
+                                   (format stream "~@<Signal an exceptional test failure and abort the test ~S.~@:>" test))
                          (abort-test (make-instance 'test-failure :test-case test
                                                     :reason "Failure restart."))))
                      result-list))))
@@ -185,7 +195,7 @@ run."))
 
 ;;;; ** Public entry points
 
-(defun run! (test-spec)
+(defun run! (&optional (test-spec *suite*))
   "Equivalent to (explain (run TEST-SPEC))."
   (explain! (run test-spec)))