Testeez: Lightweight Unit Test Mechanism for R5RS Scheme

Testeez: Lightweight Unit Test Mechanism for R5RS Scheme

Version 0.3, 2005-05-30, `'

by Neil W. Van Dyke <>

     Copyright (C) 2005 Neil W. Van Dyke.  This program is Free
     Software; you can redistribute it and/or modify it under the terms
     of the GNU Lesser General Public License as published by the Free
     Software Foundation; either version 2.1 of the License, or (at
     your option) any later version.  This program is distributed in
     the hope that it will be useful, but without any warranty; without
     even the implied warranty of merchantability or fitness for a
     particular purpose.  See <>
     for details.  For other license options and consulting, contact
     the author.


Testeez is a simple lightweight unit test mechanism for R5RS Scheme.  It
was written to support regression test suites embedded within the source
code files of the author's portable Scheme libraries.

   A series of Testeez tests is listed within the `testeez' syntax.  By
following a simple convention, these tests can be disabled and the
dependency on Testeez removed for production code.  For example, to use
Testeez in a "Foo" library, one can first add a syntax wrapper around
`testeez' like so:

     (define-syntax %foo:testeez
       (syntax-rules ()
         ((_ X ...)
          ;; Note: Comment-out exactly one of the following two lines.
          ;; (error "Tests disabled.")
          (testeez X ...)

   Then, this wrapper `%foo:testeez' can be used in a procedure that
executes the test suite of the "Foo" library:

     (define (%foo:test)
        "Foo Station"

        (test/equal "Put two and two together" (+ 2 2) 4)

        (test-define "Bar function" bar (lambda (x) (+ x 42)))

        (test/equal "Bar scene" (bar 69) 0)

        (test/eqv   "Full circle" (* (bar -21) 2) 42)

        (test/eqv   "Multiple"
                    (values (+ 2 2) (string #\h #\i) (char-upcase #\p))
                    (values 4 "hi" #\P))))

   When the tests are enabled and `(%foo:test)' is evaluated, output
like the following (which looks prettier fontified in Emacs's `*scheme*'
buffer) is printed:

     ;;; BEGIN "Foo Station" TESTS

     ;; 1. Put two and two together
     (+ 2 2)
     ;; ==> 4
     ;; Passed.

     ;; DEFINE: Bar function
     (define bar (lambda (x) (+ x 42)))

     ;; 2. Bar scene
     (bar 69)
     ;; ==> 111
     ;; FAILED!  Expected:
     ;;     0

     ;; 3. Full circle
     (* (bar -21) 2)
     ;; ==> 42
     ;; Passed.

     ;; 4. Multiple
     (values (+ 2 2) (string #\h #\i) (char-upcase #\p))
     ;; ==> 4
     ;;     "hi"
     ;;     #\P
     ;; Passed.

     ;;; END "Foo Station" TESTS: FAILED
     ;;;     (Total: 4  Passed: 3  Failed: 1)

   The `testeez' syntax also supports shorthand or abbreviated forms,
for quick interactive use, such as in an editor buffer while
rapid-prototyping a function, and in a REPL while debugging.  For an
example of shorthand, the Scheme expression:

     (testeez ((+ 1 2) 3) ((* 6 7) 42))

is equivalent to:

     (testeez ""
              (test/equal "" (+ 1 2) 3)
              (test/equal "" (* 6 7) 42))

   Future versions of Testeez will add additional features, such as
custom predicates and handling of errors.


The interface consists of the `testeez' syntax.

> (testeez [ title ] form ...)
     The `testeez' syntax contains a short string TITLE and one or more
     FORMS, of the following syntaxes, which are evaluated in order.

    `(test/equal DESC EXPR EXPECTED)'
          Execute a test case.  DESC is a short title or description of
          the test case, EXPR is a Scheme expression, and EXPECTED is an
          expression for the expected value (or multiple values).  The
          test case passes iff each value of EXPR is `equal?' to the
          corresponding value of EXPECTED.

    `(test/eq DESC EXPR EXPECTED)'
          Like `test/equal', except the equivalence predicate is `eq?'
          rather than `equal?'.

    `(test/eqv DESC EXPR EXPECTED)'
          Like `test/equal', except the equivalence predicate is `eqv?'
          rather than `equal?'.

    `(test-define DESC NAME VAL)'
          Bind a variable.  DESC is a short description string, NAME is
          the identifier, and VAL is the value expression.  The binding
          is visible to the remainder of the enclosing `testeez' syntax.

    `(test-eval DESC EXPR)'
          Evaluate an expression.

          Shorthand for `(test/equal "" EXPR EXPECTED)'.  This
          shorthand is intended for interactive and rapid-prototyping
          use, not for released code.


Version 0.3 -- 2005-05-30
     Shorthand syntax added.  Minor formatting change to test log

Version 0.2 -- 2005-03-07
     Multiple values are now supported.  `test/eq' and `test/eqv' have
     been added.  Minor formatting changes to test log output.

Version 0.1 -- 2005-01-02
     Initial release.