123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- ;; Copyright 1996, 1997, 1998 Per Bothner.
- ;;
- ;; Usage:
- ;; (load "testing.scm")
- ;; (test-init "Miscellaneous" 2)
- ;; (test '(3 4 5 6) (lambda x x) 3 4 5 6)
- ;; (test '(a b c . d) 'dot '(a . (b . (c . d))))
- ;; (test-report)
- ;;
- ;; test-init: The first argument is the name of the test.
- ;; A log is written to (string-append NAME ".log").
- ;; The second (optional) argument is the total number of tests;
- ;; at the end an error is written if the actual count does not match.
- ;;
- ;; test: The first argument is the expected result.
- ;; The second argument is either a procecure applied to the remaining
- ;; arguments; or it is a symbol (used when reporting), in which case
- ;; the third argument is matched against the first.
- ;; The resulting values are matched using equal?.
- ;;
- ;; section: You can divide your tests into "sections" with the section
- ;; procedure. The arguments of the previous section are displayed if any
- ;; errors are reported.
- ;;
- ;; test-report: Called at end to print a summary.
- ;;
- ;; fail-expected: If non-false, if means the following test is
- ;; expected to fail. The actual value should be string explaining
- ;; the failure. For example:
- ;; (set! fail-expected "sqrt of negative number not supported")
- ;; (test "+2.0i" number->string (sqrt -4))
- ;;
- ;; verbose: If true, all tests are written to standard output,
- ;; not just to the log file.
- (define verbose #f)
- (define pass-count 0)
- (define fail-count 0)
- (define xfail-count 0)
- (define xpass-count 0)
- (define *log-file* #f)
- (define test-name "<unknown>")
- ;;; Set this (to an explanatory string) if the next test is known to fail.
- (define-variable fail-expected #f)
- ;;; The current section.
- (define cur-section #f)
- ;;; The section when we last emitted a message.
- (define last-section #f)
- (define total-expected-count #f)
- (define (test-init name #!optional total-count)
- (set! test-name name)
- (set! total-expected-count total-count)
- (set! *log-file* (open-output-file (string-append name ".log")))
- (display (string-append "%%%% Starting test " name) *log-file*)
- (newline *log-file*)
- (display (string-append "%%%% Starting test " name
- " (Writing full log to \"" name ".log\")"))
- (newline)
- (set! pass-count 0)
- (set! xpass-count 0)
- (set! fail-count 0)
- (set! xfail-count 0))
- (define (display-section port)
- (display "SECTION" port)
- (do ((l cur-section (cdr l)))
- ((null? l) #f)
- (write-char #\Space port)
- (display (car l) port))
- (newline port))
- (define (maybe-report-section)
- (and cur-section *log-file* (not (eq? cur-section last-section))
- (begin (display-section (current-output-port))
- (set! last-section cur-section))))
- (define (section . args)
- (set! cur-section args)
- (display-section (or *log-file* (current-output-port)))
- (set! last-section #f))
- (define record-error (lambda (e) (set! errs (cons (list cur-section e) errs))))
- (define (report-pass port fun args res)
- (display (if fail-expected "XPASS:" "PASS: ") port)
- (write (cons fun args) port)
- (display " ==> " port)
- (write res port)
- (newline port))
- (define (report-fail port fun args res expect)
- (display (cond ((string? fail-expected)
- (string-append "XFAIL (" fail-expected "): "))
- (fail-expected "XFAIL: ")
- (else "FAIL: "))
- port)
- (write (cons fun args) port)
- (display " ==> " port)
- (write res port)
- (display " BUT EXPECTED " port)
- (write expect port)
- (newline port))
- #|
- (define-syntax test
- (syntax-rules ()
- ((test expect fun . args)
- (cons #t (test1 (source-filename) (source-line) expect fun . args)))))
- |#
- ;; test.scm redefines + in one of its tests. This causes problems when we
- ;; want to use '+ in the test function below. The clean (future) solution
- ;; would be to put this file inside a module. FIXME.
- (define (test expect fun #!rest args)
- ((lambda (res)
- (cond ((equal? expect res)
- (if fail-expected
- (set! xpass-count (+ xpass-count 1))
- (set! pass-count (+ pass-count 1)))
- (if *log-file*
- (report-pass *log-file* fun args res))
- (cond ((or verbose fail-expected)
- (maybe-report-section)
- (report-pass (current-output-port) fun args res))))
- (#t
- (if fail-expected
- (set! xfail-count (+ xfail-count 1))
- (set! fail-count (+ fail-count 1)))
- (if *log-file*
- (report-fail *log-file* fun args res expect))
- (cond ((or verbose (not fail-expected))
- (maybe-report-section)
- (report-fail (current-output-port) fun args res expect)))))
- (set! fail-expected #f))
- (if (procedure? fun)
- (cond-expand (kawa
- (try-catch
- (apply fun args)
- (ex <java.lang.Throwable>
- ;; (invoke ex 'printStackTrace) ;; for DEBUGGING
- ex)))
- (else
- (apply fun args)))
- (car args))))
- (define (report-display value)
- (display value)
- (and *log-file* (display value *log-file*)))
- (define (report-newline)
- (newline)
- (and *log-file* (newline *log-file*)))
- (define (report1 value string)
- (cond ((> value 0)
- (report-display string)
- (report-display value)
- (report-newline))))
- (define (test-report)
- (report1 pass-count "# of expected passes ")
- (report1 xfail-count "# of expected failures ")
- (report1 xpass-count "# of unexpected successes ")
- (report1 fail-count "# of unexpected failures ")
- (if (and total-expected-count
- (not (= total-expected-count
- (+ pass-count xfail-count xpass-count fail-count))))
- (begin
- (report-display "*** Total number of tests should be: ")
- (report-display total-expected-count)
- (report-display ". ***")
- (report-newline)
- (report-display "*** Discrepancy indicates testsuite error or exceptions. ***")
- (report-newline)))
- (cond (*log-file*
- (close-output-port *log-file*)
- (set! *log-file* #f))))
|