chickadee » test


Yet another testing utility.


(require-extension test)

;; Simple test
(test 4 (+ 2 2))

;; group
(test-group "A group"
  (test "A test with description" 5 (+ 2 3))
  (test-assert "This should always be true" (string? "foo")))

;; IMPORTANT! The following ensures nightly automated tests can
;; distinguish failure from success.  Always end tests/run.scm with this.


This is designed to be as simple and friendly as possible.

(test [<name>] <expected-value> <expression>) syntax

The basic test interface; really all you need to use. It will catch errors and print informative failure messages, including the name (which must be a string if present, and defaults to an abbreviated form of the test expression), the source, and the line number information of the failed expression. Equality is checked with EQUAL?, unless the expected value is inexact, in which case it checks to be sure the percentage difference (or absolute difference if one value is zero) between the result and expected value fall within the TEST-EPSILON parameter of each other. This is because it almost never makes sense to test inexact numbers with EQUAL? or =, and usually you'll want a single epsilon throughout a range of tests. However, you can always test = manually with TEST-ASSERT.

(test-assert [<name>] <expression>) syntax
(test-error [<name>] <expression>) syntax

Convenience wrappers around test. test-assert asserts that the expression is non-false; test-error asserts that the expression results in an error.

(test-begin [<name>]) syntax
(test-end [<name>]) syntax

Test group reporting, including elapsed time and pass percentages, can be achieved using

 (test-begin [<name>])
 (test ...)
 (test-end [<name>])

where the group name is optional in either case.

(test-group <name> ...) syntax

You can group tests in a single lexical scope (and also establish nested groups) with the test-group macro:

 (test-group <name>
   (test ...)

The name for test-group is not optional.

(test-exit [<failure-exit-code>]) procedure

As a convenience there is a test-exit procedure, which exits the process with a status of 0 if all tests in all groups have passed, and with an optional numeric status (defaulting to 1), if there have been any failures or errors.


All other aspects of testing are controlled by parameters.

current-test-verbosity parameter

Default to #t, prints full diagnostics for failures

current-test-epsilon parameter

Percentage difference allowed for inexact comparisons

current-test-comparator parameter


current-test-filters parameter

List of predicates to filter (not run) tests

current-test-group-filters parameter

List of predicates to filter entire test groups

current-test-applier parameter
current-test-handler parameter
current-test-skipper parameter
current-test-group-reporter parameter

These parameters can be used to override the reporting behavior, for example if you wanted a GUI interface instead of the default textual reporting.


Often you'll be working on a change or new feature, and while the code is changing the test suite remains relatively constant. However, it's a pain to recompile the test suite every time, and to re-run the entire suite when just working on one area, or even when you just want to run a single test by name.

The parameters allow filtering, but it can be a pain to setup an interface to this or to recompile with different settings. So for easy use, by default the parameters can be initialized from environment variables.

CURRENT-TEST-FILTERS can be set by the environment variables TEST_FILTER, a regexp which test names must match to be run, and TEST_REMOVE, a regexp of tests not to run. For example, if you have your test suite in the file test-foo.scm, compiled to test-foo, and you only want to run the test named "test-foo-with-bells-on," you could do so with

 $ TEST_FILTER=bells-on ./test-foo

The test name defaults to the source expression, which can also be handy for quick filtering. For instance, if in the same test suite you knew that you had broken the "flurble" data structure, you could filter out all tests using it with

 $ TEST_REMOVE=flurble- ./test-foo

For more structured filtering you can also filter by group. The CURRENT-TEST-GROUP-FILTERS parameter can be initialized with the TEST_GROUP_FILTER and TEST_GROUP_REMOVE environment variables in the same way as above.

You can also default the CURRENT-TEST-VERBOSITY parameter to #f by setting the TEST_QUIET environment variable.

test tries to automatically determine if your terminal supports ANSI colors and uses them (sparingly, mostly so that failures and errors stand out). You can force this on or off by setting the environment variable TEST_USE_ANSI variable to 0 or 1.




Alex Shinn

Fixed bug introduced with last change to re-allow test with no group for simple cases.
Added support for less verbose tests w/ TEST_QUIET=1 env var
Added missing require-library statements for libraries that are imported by test [Peter Bex]
renamed use of deprecated getenv [felix]
added regex dependency
Port to hygienic chicken [Peter Bex]
fix for dynamic test names w/o syntax-rules [Peter Bex]
adding several TERM settings to those recognized as ANSI
fixing spurious warning in nested groups
time reporting was off
minor bugfixes
minor bugfixes
initial release

Contents »