_TEST SUITE INTERFACE_

=========================================================================
_Test Suite Quickstart_

Step 1: Define your test suite

Define a module in which to put your tests. The module you use can be either
the same module your code is in or a new one. In that module, require the 
library _tester.ss_.

In the module you choose, define and provide a function called test-main,
which must be a function of no arguments that returns void. In that function,
call the function run-tests as follows:

(run-tests "a description of this group of tests" 
   (test "description" expression-to-test expected-result) ...)

You can call run-tests as often as you want in test-main: each call will
queue a new test group for the tester.

Step 2: Run your test suite

To run your test suite, call test-manifest with a list of quoted
require-specs, each of which specifies a file of tests -- for example, if
you wanted to run test files "a.ss", "b.ss", and "c.ss", call test-manifest
like this:

(test-manifest (list '(file "a.ss")
                     '(file "b.ss")
                     '(file "c.ss")))

Each test-expression in all files listed in the manifest will be
evaluated in a special context where any printing to standard output
will be intercepted and any exceptions that it raises will be
caught. Its return value will be compared to the expected return
value, and the result of the test will be printed to a GUI window.

=========================================================================

The file _tester.ss_ defines a module named tester that provides sevem
names: run-tests, run-tests/initialize, test, test-error, test-function,
test-exit, and test-manifest. run-tests is a function that has the form:

> (run-tests str a-test ...)

Where a-test is either:

> (test str expr value [str])
> (test-error str expr str [str])
> (test-function str expr (value x str -> bool) [str])
> (test-exit str expr)

In all four forms of a-test, the first position should be a
description of the test to be performed and the second should be the
expression to be tested. For all forms but test-exit, the third
position is the "comparison datum," which is used to determine whether
or not the test should pass, and the optional fourth position
specifies an output string that the program must produce for the test
to pass.

The different forms determine if the test should pass based on the
following rules:

* test tests the value produced by evaluating the given expression and
  comparing it using equal? to the given expected value. If evaluating
  the expression results in an error being raised, the test automatically 
  fails.

* test-error tests the error raised as a result of evaluating the
  given expression to see if it has the same error message string as
  the given string. If the expression evaluates to a value without
  raising an exception, the test fails.

* test-function applies the given function to the value produced by
  the expression (if the optional string was provided) or the value
  produced by the expression and the printed output of the expression
  (if the optional string was not provided). If evaluating the
  expression results in an error being raised, the test fails.

* test-exit passes if and only if the test-thunk kills its own thread
  or calls exit.

run-tests/initialize is a function that has the form

> (run-tests/initialize str (-> void) a-test ...)

where a-test is the same as the tests for run-test. run-tests/initialize
behaves like run-tests except that it evaluates the given thunk before
evaluating any of the test expressions.

All tests will run in the same eventspace on which the initializer runs,
which is a different eventspace from the tester's. If a test thunk exits
or kills its own thread, a fresh eventspace is created and the initializer
is run again on that thread, after which the remaining tests run.
