Mercurial > hg > xemacs-beta
diff tests/automated/test-harness.el @ 5125:b5df3737028a ben-lisp-object
merge
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Wed, 24 Feb 2010 01:58:04 -0600 |
parents | e813cf16c015 |
children | 3daf9fc57cd4 |
line wrap: on
line diff
--- a/tests/automated/test-harness.el Wed Jan 20 07:05:57 2010 -0600 +++ b/tests/automated/test-harness.el Wed Feb 24 01:58:04 2010 -0600 @@ -1,7 +1,7 @@ ;; test-harness.el --- Run Emacs Lisp test suites. ;;; Copyright (C) 1998, 2002, 2003 Free Software Foundation, Inc. -;;; Copyright (C) 2002 Ben Wing. +;;; Copyright (C) 2002, 2010 Ben Wing. ;; Author: Martin Buchholz ;; Maintainer: Stephen J. Turnbull <stephen@xemacs.org> @@ -115,6 +115,12 @@ (length "byte-compiler-tests.el:")) ; use the longest file name "Format for \"No tests\" lines printed after a file is run.") +(defconst test-harness-aborted-summary-template + (format "%%-%ds %%%dd tests completed (aborted)." + (length "byte-compiler-tests.el:") ; use the longest file name + 5) + "Format for summary lines printed after a test run on a file was aborted.") + ;;;###autoload (defun test-emacs-test-file (filename) "Test a file of Lisp code named FILENAME. @@ -209,12 +215,20 @@ (defconst test-harness-failure-tag "FAIL") (defconst test-harness-success-tag "PASS") +;;;;; BEGIN DEFINITION OF MACROS USEFUL IN TEST CODE + (defmacro Known-Bug-Expect-Failure (&rest body) + "Wrap a BODY that consists of tests that are known to fail. +This causes messages to be printed on failure indicating that this is expected, +and on success indicating that this is unexpected." `(let ((test-harness-failure-tag "KNOWN BUG") (test-harness-success-tag "PASS (FAILURE EXPECTED)")) ,@body)) (defmacro Known-Bug-Expect-Error (expected-error &rest body) + "Wrap a BODY that consists of tests that are known to trigger an error. +This causes messages to be printed on failure indicating that this is expected, +and on success indicating that this is unexpected." (let ((quoted-body (if (= 1 (length body)) `(quote ,(car body)) `(quote (progn ,@body))))) `(let ((test-harness-failure-tag "KNOWN BUG") @@ -237,6 +251,10 @@ (incf wrong-error-failures)))))) (defmacro Implementation-Incomplete-Expect-Failure (&rest body) + "Wrap a BODY containing tests that are known to fail due to incomplete code. +This causes messages to be printed on failure indicating that the +implementation is incomplete (and hence the failure is expected); and on +success indicating that this is unexpected." `(let ((test-harness-failure-tag "IMPLEMENTATION INCOMPLETE") (test-harness-success-tag "PASS (FAILURE EXPECTED)")) ,@body)) @@ -269,28 +287,118 @@ (defmacro Assert (assertion &optional failing-case description) "Test passes if ASSERTION is true. -Optional FAILING-CASE describes the particular failure. -Optional DESCRIPTION describes the assertion. -FAILING-CASE and DESCRIPTION are useful when Assert is used in a loop." - `(condition-case error-info - (progn - (assert ,assertion) - (Print-Pass "%S" (quote ,(or description assertion))) - (incf passes)) - (cl-assertion-failed - (Print-Failure (if ,failing-case - "Assertion failed: %S; failing case = %S" - "Assertion failed: %S") - (quote ,(or description assertion)) ,failing-case) - (incf assertion-failures)) - (t (Print-Failure (if ,failing-case - "%S ==> error: %S; failing case = %S" - "%S ==> error: %S") - (quote ,(or description assertion)) - error-info ,failing-case) - (incf other-failures) - ))) +Optional FAILING-CASE describes the particular failure. Optional +DESCRIPTION describes the assertion; by default, the unevalated assertion +expression is given. FAILING-CASE and DESCRIPTION are useful when Assert +is used in a loop." + (let ((description + (or description `(quote ,assertion)))) + `(condition-case error-info + (progn + (assert ,assertion) + (Print-Pass "%S" ,description) + (incf passes)) + (cl-assertion-failed + (Print-Failure (if ,failing-case + "Assertion failed: %S; failing case = %S" + "Assertion failed: %S") + ,description ,failing-case) + (incf assertion-failures)) + (t (Print-Failure (if ,failing-case + "%S ==> error: %S; failing case = %S" + "%S ==> error: %S") + ,description error-info ,failing-case) + (incf other-failures) + )))) + +;;;;; BEGIN DEFINITION OF SPECIFIC KINDS OF ASSERT MACROS + + (defmacro Assert-test (test testval expected &optional failing-case + description) + "Test passes if TESTVAL compares correctly to EXPECTED using TEST. +TEST should be a two-argument predicate (i.e. a function of two arguments +that returns t or nil), such as `eq', `eql', `equal', `equalp', `=', `<=', +'>', 'file-newer-than-file-p' etc. Optional FAILING-CASE describes the +particular failure; any value given here will be concatenated with a phrase +describing the expected and actual values of the comparison. Optional +DESCRIPTION describes the assertion; by default, the unevalated comparison +expressions are given. FAILING-CASE and DESCRIPTION are useful when Assert +is used in a loop." + (let* ((assertion `(,test ,testval ,expected)) + (failmsg `(format "%S should be `%s' to %S but isn't" + ,testval ',test ,expected)) + (failmsg2 (if failing-case `(concat + (format "%S, " ,failing-case) + ,failmsg) + failmsg))) + `(Assert ,assertion ,failmsg2 ,description))) + (defmacro Assert-test-not (test testval expected &optional failing-case + description) + "Test passes if TESTVAL does not compare correctly to EXPECTED using TEST. +TEST should be a two-argument predicate (i.e. a function of two arguments +that returns t or nil), such as `eq', `eql', `equal', `equalp', `=', `<=', +'>', 'file-newer-than-file-p' etc. Optional FAILING-CASE describes the +particular failure; any value given here will be concatenated with a phrase +describing the expected and actual values of the comparison. Optional +DESCRIPTION describes the assertion; by default, the unevalated comparison +expressions are given. FAILING-CASE and DESCRIPTION are useful when Assert +is used in a loop." + (let* ((assertion `(not (,test ,testval ,expected))) + (failmsg `(format "%S shouldn't be `%s' to %S but is" + ,testval ',test ,expected)) + (failmsg2 (if failing-case `(concat + (format "%S, " ,failing-case) + ,failmsg) + failmsg))) + `(Assert ,assertion ,failmsg2 ,description))) + + ;; Specific versions of `Assert-test'. These are just convenience + ;; functions, functioning identically to `Assert-test', and duplicating + ;; the doc string for each would be too annoying. + (defmacro Assert-eq (testval expected &optional failing-case + description) + `(Assert-test eq ,testval ,expected ,failing-case ,description)) + (defmacro Assert-eql (testval expected &optional failing-case + description) + `(Assert-test eql ,testval ,expected ,failing-case ,description)) + (defmacro Assert-equal (testval expected &optional failing-case + description) + `(Assert-test equal ,testval ,expected ,failing-case ,description)) + (defmacro Assert-equalp (testval expected &optional failing-case + description) + `(Assert-test equalp ,testval ,expected ,failing-case ,description)) + (defmacro Assert-string= (testval expected &optional failing-case + description) + `(Assert-test string= ,testval ,expected ,failing-case ,description)) + (defmacro Assert= (testval expected &optional failing-case + description) + `(Assert-test = ,testval ,expected ,failing-case ,description)) + (defmacro Assert<= (testval expected &optional failing-case + description) + `(Assert-test <= ,testval ,expected ,failing-case ,description)) + + ;; Specific versions of `Assert-test-not'. These are just convenience + ;; functions, functioning identically to `Assert-test-not', and + ;; duplicating the doc string for each would be too annoying. + (defmacro Assert-not-eq (testval expected &optional failing-case + description) + `(Assert-test-not eq ,testval ,expected ,failing-case ,description)) + (defmacro Assert-not-eql (testval expected &optional failing-case + description) + `(Assert-test-not eql ,testval ,expected ,failing-case ,description)) + (defmacro Assert-not-equal (testval expected &optional failing-case + description) + `(Assert-test-not equal ,testval ,expected ,failing-case ,description)) + (defmacro Assert-not-equalp (testval expected &optional failing-case + description) + `(Assert-test-not equalp ,testval ,expected ,failing-case ,description)) + (defmacro Assert-not-string= (testval expected &optional failing-case + description) + `(Assert-test-not string= ,testval ,expected ,failing-case ,description)) + (defmacro Assert-not= (testval expected &optional failing-case + description) + `(Assert-test-not = ,testval ,expected ,failing-case ,description)) (defmacro Check-Error (expected-error &rest body) (let ((quoted-body (if (= 1 (length body)) @@ -396,7 +504,7 @@ (princ (format "Unexpected error %S while executing interpreted code\n" error-info)) (message "Unexpected error %S while executing interpreted code." error-info) - (message "Test suite execution aborted." error-info) + (message "Test suite execution aborted.") )) (princ "\nTesting Compiled Lisp\n\n") (let (code @@ -417,7 +525,7 @@ (princ (format "Unexpected error %S while executing byte-compiled code\n" error-info)) (message "Unexpected error %S while executing byte-compiled code." error-info) - (message "Test suite execution aborted." error-info) + (message "Test suite execution aborted.") ))) (princ (format "\nSUMMARY for %s:\n" filename)) (princ (format "\t%5d passes\n" passes)) @@ -434,12 +542,16 @@ other-failures)) (basename (file-name-nondirectory filename)) (summary-msg - (if (> total 0) - (format test-harness-file-summary-template - (concat basename ":") - passes total (/ (* 100 passes) total)) - (format test-harness-null-summary-template - (concat basename ":")))) + (cond ((> unexpected-test-file-failures 0) + (format test-harness-aborted-summary-template + (concat basename ":") total)) + ((> total 0) + (format test-harness-file-summary-template + (concat basename ":") + passes total (/ (* 100 passes) total))) + (t + (format test-harness-null-summary-template + (concat basename ":"))))) (reasons "")) (maphash (lambda (key value) (setq reasons @@ -530,7 +642,10 @@ Use this from the command line, with `-batch'; it won't work in an interactive Emacs. Each file is processed even if an error occurred previously. -For example, invoke \"xemacs -batch -f batch-test-emacs tests/*.el\"" +A directory can be given as well, and all files will be processed -- +however, the file test-harness.el, which implements the test harness, +will be skipped. +For example, invoke \"xemacs -batch -f batch-test-emacs tests\"" ;; command-line-args-left is what is left of the command line (from ;; startup.el) (defvar command-line-args-left) ;Avoid 'free variable' warning @@ -579,14 +694,19 @@ (basename (file-name-nondirectory (first head))) (nsucc (second head)) (ntest (third head))) - (if (> ntest 0) - (message test-harness-file-summary-template - (concat basename ":") - nsucc - ntest - (/ (* 100 nsucc) ntest)) - (message test-harness-null-summary-template - (concat basename ":"))) + (cond ((member (first head) unexpected-test-suite-failure-files) + (message test-harness-aborted-summary-template + (concat basename ":") + ntest)) + ((> ntest 0) + (message test-harness-file-summary-template + (concat basename ":") + nsucc + ntest + (/ (* 100 nsucc) ntest))) + (t + (message test-harness-null-summary-template + (concat basename ":")))) (setq results (cdr results))))) (when (> unexpected-test-suite-failures 0) (message "\n***** There %s %d unexpected test suite %s in %s:"