comparison 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
comparison
equal deleted inserted replaced
5124:623d57b7fbe8 5125:b5df3737028a
1 ;; test-harness.el --- Run Emacs Lisp test suites. 1 ;; test-harness.el --- Run Emacs Lisp test suites.
2 2
3 ;;; Copyright (C) 1998, 2002, 2003 Free Software Foundation, Inc. 3 ;;; Copyright (C) 1998, 2002, 2003 Free Software Foundation, Inc.
4 ;;; Copyright (C) 2002 Ben Wing. 4 ;;; Copyright (C) 2002, 2010 Ben Wing.
5 5
6 ;; Author: Martin Buchholz 6 ;; Author: Martin Buchholz
7 ;; Maintainer: Stephen J. Turnbull <stephen@xemacs.org> 7 ;; Maintainer: Stephen J. Turnbull <stephen@xemacs.org>
8 ;; Keywords: testing 8 ;; Keywords: testing
9 9
113 (defconst test-harness-null-summary-template 113 (defconst test-harness-null-summary-template
114 (format "%%-%ds No tests run." 114 (format "%%-%ds No tests run."
115 (length "byte-compiler-tests.el:")) ; use the longest file name 115 (length "byte-compiler-tests.el:")) ; use the longest file name
116 "Format for \"No tests\" lines printed after a file is run.") 116 "Format for \"No tests\" lines printed after a file is run.")
117 117
118 (defconst test-harness-aborted-summary-template
119 (format "%%-%ds %%%dd tests completed (aborted)."
120 (length "byte-compiler-tests.el:") ; use the longest file name
121 5)
122 "Format for summary lines printed after a test run on a file was aborted.")
123
118 ;;;###autoload 124 ;;;###autoload
119 (defun test-emacs-test-file (filename) 125 (defun test-emacs-test-file (filename)
120 "Test a file of Lisp code named FILENAME. 126 "Test a file of Lisp code named FILENAME.
121 The output file's name is made by appending `c' to the end of FILENAME." 127 The output file's name is made by appending `c' to the end of FILENAME."
122 (interactive 128 (interactive
207 (princ (format "Testing %s...\n\n" filename)) 213 (princ (format "Testing %s...\n\n" filename))
208 214
209 (defconst test-harness-failure-tag "FAIL") 215 (defconst test-harness-failure-tag "FAIL")
210 (defconst test-harness-success-tag "PASS") 216 (defconst test-harness-success-tag "PASS")
211 217
218 ;;;;; BEGIN DEFINITION OF MACROS USEFUL IN TEST CODE
219
212 (defmacro Known-Bug-Expect-Failure (&rest body) 220 (defmacro Known-Bug-Expect-Failure (&rest body)
221 "Wrap a BODY that consists of tests that are known to fail.
222 This causes messages to be printed on failure indicating that this is expected,
223 and on success indicating that this is unexpected."
213 `(let ((test-harness-failure-tag "KNOWN BUG") 224 `(let ((test-harness-failure-tag "KNOWN BUG")
214 (test-harness-success-tag "PASS (FAILURE EXPECTED)")) 225 (test-harness-success-tag "PASS (FAILURE EXPECTED)"))
215 ,@body)) 226 ,@body))
216 227
217 (defmacro Known-Bug-Expect-Error (expected-error &rest body) 228 (defmacro Known-Bug-Expect-Error (expected-error &rest body)
229 "Wrap a BODY that consists of tests that are known to trigger an error.
230 This causes messages to be printed on failure indicating that this is expected,
231 and on success indicating that this is unexpected."
218 (let ((quoted-body (if (= 1 (length body)) 232 (let ((quoted-body (if (= 1 (length body))
219 `(quote ,(car body)) `(quote (progn ,@body))))) 233 `(quote ,(car body)) `(quote (progn ,@body)))))
220 `(let ((test-harness-failure-tag "KNOWN BUG") 234 `(let ((test-harness-failure-tag "KNOWN BUG")
221 (test-harness-success-tag "PASS (FAILURE EXPECTED)")) 235 (test-harness-success-tag "PASS (FAILURE EXPECTED)"))
222 (condition-case error-info 236 (condition-case error-info
235 (Print-Failure "%S ==> expected error %S, got error %S instead" 249 (Print-Failure "%S ==> expected error %S, got error %S instead"
236 ,quoted-body ',expected-error error-info) 250 ,quoted-body ',expected-error error-info)
237 (incf wrong-error-failures)))))) 251 (incf wrong-error-failures))))))
238 252
239 (defmacro Implementation-Incomplete-Expect-Failure (&rest body) 253 (defmacro Implementation-Incomplete-Expect-Failure (&rest body)
254 "Wrap a BODY containing tests that are known to fail due to incomplete code.
255 This causes messages to be printed on failure indicating that the
256 implementation is incomplete (and hence the failure is expected); and on
257 success indicating that this is unexpected."
240 `(let ((test-harness-failure-tag "IMPLEMENTATION INCOMPLETE") 258 `(let ((test-harness-failure-tag "IMPLEMENTATION INCOMPLETE")
241 (test-harness-success-tag "PASS (FAILURE EXPECTED)")) 259 (test-harness-success-tag "PASS (FAILURE EXPECTED)"))
242 ,@body)) 260 ,@body))
243 261
244 (defun Print-Failure (fmt &rest args) 262 (defun Print-Failure (fmt &rest args)
267 (Print-Skip ,description ,reason)) 285 (Print-Skip ,description ,reason))
268 ,@body)) 286 ,@body))
269 287
270 (defmacro Assert (assertion &optional failing-case description) 288 (defmacro Assert (assertion &optional failing-case description)
271 "Test passes if ASSERTION is true. 289 "Test passes if ASSERTION is true.
272 Optional FAILING-CASE describes the particular failure. 290 Optional FAILING-CASE describes the particular failure. Optional
273 Optional DESCRIPTION describes the assertion. 291 DESCRIPTION describes the assertion; by default, the unevalated assertion
274 FAILING-CASE and DESCRIPTION are useful when Assert is used in a loop." 292 expression is given. FAILING-CASE and DESCRIPTION are useful when Assert
275 `(condition-case error-info 293 is used in a loop."
276 (progn 294 (let ((description
277 (assert ,assertion) 295 (or description `(quote ,assertion))))
278 (Print-Pass "%S" (quote ,(or description assertion))) 296 `(condition-case error-info
279 (incf passes)) 297 (progn
280 (cl-assertion-failed 298 (assert ,assertion)
281 (Print-Failure (if ,failing-case 299 (Print-Pass "%S" ,description)
282 "Assertion failed: %S; failing case = %S" 300 (incf passes))
283 "Assertion failed: %S") 301 (cl-assertion-failed
284 (quote ,(or description assertion)) ,failing-case) 302 (Print-Failure (if ,failing-case
285 (incf assertion-failures)) 303 "Assertion failed: %S; failing case = %S"
286 (t (Print-Failure (if ,failing-case 304 "Assertion failed: %S")
287 "%S ==> error: %S; failing case = %S" 305 ,description ,failing-case)
288 "%S ==> error: %S") 306 (incf assertion-failures))
289 (quote ,(or description assertion)) 307 (t (Print-Failure (if ,failing-case
290 error-info ,failing-case) 308 "%S ==> error: %S; failing case = %S"
291 (incf other-failures) 309 "%S ==> error: %S")
292 ))) 310 ,description error-info ,failing-case)
293 311 (incf other-failures)
312 ))))
313
314 ;;;;; BEGIN DEFINITION OF SPECIFIC KINDS OF ASSERT MACROS
315
316 (defmacro Assert-test (test testval expected &optional failing-case
317 description)
318 "Test passes if TESTVAL compares correctly to EXPECTED using TEST.
319 TEST should be a two-argument predicate (i.e. a function of two arguments
320 that returns t or nil), such as `eq', `eql', `equal', `equalp', `=', `<=',
321 '>', 'file-newer-than-file-p' etc. Optional FAILING-CASE describes the
322 particular failure; any value given here will be concatenated with a phrase
323 describing the expected and actual values of the comparison. Optional
324 DESCRIPTION describes the assertion; by default, the unevalated comparison
325 expressions are given. FAILING-CASE and DESCRIPTION are useful when Assert
326 is used in a loop."
327 (let* ((assertion `(,test ,testval ,expected))
328 (failmsg `(format "%S should be `%s' to %S but isn't"
329 ,testval ',test ,expected))
330 (failmsg2 (if failing-case `(concat
331 (format "%S, " ,failing-case)
332 ,failmsg)
333 failmsg)))
334 `(Assert ,assertion ,failmsg2 ,description)))
335
336 (defmacro Assert-test-not (test testval expected &optional failing-case
337 description)
338 "Test passes if TESTVAL does not compare correctly to EXPECTED using TEST.
339 TEST should be a two-argument predicate (i.e. a function of two arguments
340 that returns t or nil), such as `eq', `eql', `equal', `equalp', `=', `<=',
341 '>', 'file-newer-than-file-p' etc. Optional FAILING-CASE describes the
342 particular failure; any value given here will be concatenated with a phrase
343 describing the expected and actual values of the comparison. Optional
344 DESCRIPTION describes the assertion; by default, the unevalated comparison
345 expressions are given. FAILING-CASE and DESCRIPTION are useful when Assert
346 is used in a loop."
347 (let* ((assertion `(not (,test ,testval ,expected)))
348 (failmsg `(format "%S shouldn't be `%s' to %S but is"
349 ,testval ',test ,expected))
350 (failmsg2 (if failing-case `(concat
351 (format "%S, " ,failing-case)
352 ,failmsg)
353 failmsg)))
354 `(Assert ,assertion ,failmsg2 ,description)))
355
356 ;; Specific versions of `Assert-test'. These are just convenience
357 ;; functions, functioning identically to `Assert-test', and duplicating
358 ;; the doc string for each would be too annoying.
359 (defmacro Assert-eq (testval expected &optional failing-case
360 description)
361 `(Assert-test eq ,testval ,expected ,failing-case ,description))
362 (defmacro Assert-eql (testval expected &optional failing-case
363 description)
364 `(Assert-test eql ,testval ,expected ,failing-case ,description))
365 (defmacro Assert-equal (testval expected &optional failing-case
366 description)
367 `(Assert-test equal ,testval ,expected ,failing-case ,description))
368 (defmacro Assert-equalp (testval expected &optional failing-case
369 description)
370 `(Assert-test equalp ,testval ,expected ,failing-case ,description))
371 (defmacro Assert-string= (testval expected &optional failing-case
372 description)
373 `(Assert-test string= ,testval ,expected ,failing-case ,description))
374 (defmacro Assert= (testval expected &optional failing-case
375 description)
376 `(Assert-test = ,testval ,expected ,failing-case ,description))
377 (defmacro Assert<= (testval expected &optional failing-case
378 description)
379 `(Assert-test <= ,testval ,expected ,failing-case ,description))
380
381 ;; Specific versions of `Assert-test-not'. These are just convenience
382 ;; functions, functioning identically to `Assert-test-not', and
383 ;; duplicating the doc string for each would be too annoying.
384 (defmacro Assert-not-eq (testval expected &optional failing-case
385 description)
386 `(Assert-test-not eq ,testval ,expected ,failing-case ,description))
387 (defmacro Assert-not-eql (testval expected &optional failing-case
388 description)
389 `(Assert-test-not eql ,testval ,expected ,failing-case ,description))
390 (defmacro Assert-not-equal (testval expected &optional failing-case
391 description)
392 `(Assert-test-not equal ,testval ,expected ,failing-case ,description))
393 (defmacro Assert-not-equalp (testval expected &optional failing-case
394 description)
395 `(Assert-test-not equalp ,testval ,expected ,failing-case ,description))
396 (defmacro Assert-not-string= (testval expected &optional failing-case
397 description)
398 `(Assert-test-not string= ,testval ,expected ,failing-case ,description))
399 (defmacro Assert-not= (testval expected &optional failing-case
400 description)
401 `(Assert-test-not = ,testval ,expected ,failing-case ,description))
294 402
295 (defmacro Check-Error (expected-error &rest body) 403 (defmacro Check-Error (expected-error &rest body)
296 (let ((quoted-body (if (= 1 (length body)) 404 (let ((quoted-body (if (= 1 (length body))
297 `(quote ,(car body)) `(quote (progn ,@body))))) 405 `(quote ,(car body)) `(quote (progn ,@body)))))
298 `(condition-case error-info 406 `(condition-case error-info
394 (error 502 (error
395 (incf unexpected-test-file-failures) 503 (incf unexpected-test-file-failures)
396 (princ (format "Unexpected error %S while executing interpreted code\n" 504 (princ (format "Unexpected error %S while executing interpreted code\n"
397 error-info)) 505 error-info))
398 (message "Unexpected error %S while executing interpreted code." error-info) 506 (message "Unexpected error %S while executing interpreted code." error-info)
399 (message "Test suite execution aborted." error-info) 507 (message "Test suite execution aborted.")
400 )) 508 ))
401 (princ "\nTesting Compiled Lisp\n\n") 509 (princ "\nTesting Compiled Lisp\n\n")
402 (let (code 510 (let (code
403 (test-harness-test-compiled t)) 511 (test-harness-test-compiled t))
404 (condition-case error-info 512 (condition-case error-info
415 (error 523 (error
416 (incf unexpected-test-file-failures) 524 (incf unexpected-test-file-failures)
417 (princ (format "Unexpected error %S while executing byte-compiled code\n" 525 (princ (format "Unexpected error %S while executing byte-compiled code\n"
418 error-info)) 526 error-info))
419 (message "Unexpected error %S while executing byte-compiled code." error-info) 527 (message "Unexpected error %S while executing byte-compiled code." error-info)
420 (message "Test suite execution aborted." error-info) 528 (message "Test suite execution aborted.")
421 ))) 529 )))
422 (princ (format "\nSUMMARY for %s:\n" filename)) 530 (princ (format "\nSUMMARY for %s:\n" filename))
423 (princ (format "\t%5d passes\n" passes)) 531 (princ (format "\t%5d passes\n" passes))
424 (princ (format "\t%5d assertion failures\n" assertion-failures)) 532 (princ (format "\t%5d assertion failures\n" assertion-failures))
425 (princ (format "\t%5d errors that should have been generated, but weren't\n" no-error-failures)) 533 (princ (format "\t%5d errors that should have been generated, but weren't\n" no-error-failures))
432 wrong-error-failures 540 wrong-error-failures
433 missing-message-failures 541 missing-message-failures
434 other-failures)) 542 other-failures))
435 (basename (file-name-nondirectory filename)) 543 (basename (file-name-nondirectory filename))
436 (summary-msg 544 (summary-msg
437 (if (> total 0) 545 (cond ((> unexpected-test-file-failures 0)
438 (format test-harness-file-summary-template 546 (format test-harness-aborted-summary-template
439 (concat basename ":") 547 (concat basename ":") total))
440 passes total (/ (* 100 passes) total)) 548 ((> total 0)
441 (format test-harness-null-summary-template 549 (format test-harness-file-summary-template
442 (concat basename ":")))) 550 (concat basename ":")
551 passes total (/ (* 100 passes) total)))
552 (t
553 (format test-harness-null-summary-template
554 (concat basename ":")))))
443 (reasons "")) 555 (reasons ""))
444 (maphash (lambda (key value) 556 (maphash (lambda (key value)
445 (setq reasons 557 (setq reasons
446 (concat reasons 558 (concat reasons
447 (format "\n %d tests skipped because %s." 559 (format "\n %d tests skipped because %s."
528 (defun batch-test-emacs () 640 (defun batch-test-emacs ()
529 "Run `test-harness' on the files remaining on the command line. 641 "Run `test-harness' on the files remaining on the command line.
530 Use this from the command line, with `-batch'; 642 Use this from the command line, with `-batch';
531 it won't work in an interactive Emacs. 643 it won't work in an interactive Emacs.
532 Each file is processed even if an error occurred previously. 644 Each file is processed even if an error occurred previously.
533 For example, invoke \"xemacs -batch -f batch-test-emacs tests/*.el\"" 645 A directory can be given as well, and all files will be processed --
646 however, the file test-harness.el, which implements the test harness,
647 will be skipped.
648 For example, invoke \"xemacs -batch -f batch-test-emacs tests\""
534 ;; command-line-args-left is what is left of the command line (from 649 ;; command-line-args-left is what is left of the command line (from
535 ;; startup.el) 650 ;; startup.el)
536 (defvar command-line-args-left) ;Avoid 'free variable' warning 651 (defvar command-line-args-left) ;Avoid 'free variable' warning
537 (defvar debug-issue-ebola-notices) 652 (defvar debug-issue-ebola-notices)
538 (if (not noninteractive) 653 (if (not noninteractive)
577 (while results 692 (while results
578 (let* ((head (car results)) 693 (let* ((head (car results))
579 (basename (file-name-nondirectory (first head))) 694 (basename (file-name-nondirectory (first head)))
580 (nsucc (second head)) 695 (nsucc (second head))
581 (ntest (third head))) 696 (ntest (third head)))
582 (if (> ntest 0) 697 (cond ((member (first head) unexpected-test-suite-failure-files)
583 (message test-harness-file-summary-template 698 (message test-harness-aborted-summary-template
584 (concat basename ":") 699 (concat basename ":")
585 nsucc 700 ntest))
586 ntest 701 ((> ntest 0)
587 (/ (* 100 nsucc) ntest)) 702 (message test-harness-file-summary-template
588 (message test-harness-null-summary-template 703 (concat basename ":")
589 (concat basename ":"))) 704 nsucc
705 ntest
706 (/ (* 100 nsucc) ntest)))
707 (t
708 (message test-harness-null-summary-template
709 (concat basename ":"))))
590 (setq results (cdr results))))) 710 (setq results (cdr results)))))
591 (when (> unexpected-test-suite-failures 0) 711 (when (> unexpected-test-suite-failures 0)
592 (message "\n***** There %s %d unexpected test suite %s in %s:" 712 (message "\n***** There %s %d unexpected test suite %s in %s:"
593 (if (= unexpected-test-suite-failures 1) "was" "were") 713 (if (= unexpected-test-suite-failures 1) "was" "were")
594 unexpected-test-suite-failures 714 unexpected-test-suite-failures