Table of Contents
Defining tests
A test is a named body of code registered in a global table at load time. The package it was defined in is its group. There are no suites, no fixtures and no dependencies between tests.
(deftest name body...)
(deftest (name &key timeout tags skip wrap serial) [docstring] body...)
deftest returns name, like defun, and expands to an ordinary macro — no
eval, no code walking.
Options
All options ride on the name, defstruct-style; nothing is sniffed from the
body.
| Option | Type | Meaning |
|---|---|---|
:timeout |
real, seconds | The body is interrupted after this many seconds of wall time; the result is an error whose message is timed out after N s. |
:tags |
list of keywords | For selection with run's :tags and :exclude. |
:skip |
string | The test does not run; its status is :skip and this string is the reason. |
:wrap |
list of forms | Each is the head of a with- macro call; the body is spliced into the last one and each wraps the next. |
:serial |
boolean | The test never runs on a worker thread. See Parallel. |
Semantics
- The displayed name is
package/name, both downcased, wherepackageis the name of*package*at definition time (not the symbol's package). A test defined in packageparser/testwith nameparse-numbersshows asparser/test/parse-numbers. - A description is a leading string followed by at least one more form; it is kept on the test object and shown by the verbose reporter. A body that is only a string is a body, not a description.
- Declarations at the start of the body are legal, with and without
:wrap. That is why:wrapsplices the body rather than wrapping it in aprogn. - Redefining a test with the same name replaces it in place and keeps its position in definition order. The order is otherwise the order of first definition.
- The body runs inside a named lambda so it appears in backtraces as
(test name), and the runner trims the backtrace there.
The :wrap option
:wrap is how you apply a with- macro to a whole test body. Each element is
the head of a macro call; assay splices the body into the innermost one, and
each head wraps the next:
(deftest (scratch-files :wrap ((with-db) (with-temp-dir (dir))))
(is (probe-file dir)))
expands, in effect, to:
(with-db
(with-temp-dir (dir)
(is (probe-file dir))))
This is assay's whole fixture story: a with- macro plus unwind-protect is
the fixture, and :wrap applies one. See Structure.
Examples
(deftest parse-empty-string
(is (null (parse ""))))
(deftest (large-input :timeout 2 :tags (:slow))
(let ((input (make-string 1000000 :initial-element #\9)))
(must (parse input) "must not blow the stack")
(is (= 1000000 (digit-count (parse input))))))
(deftest (parse-floats :skip "not implemented yet")
(is (= 1.5 (parse "1.5"))))
The registry
| Call | Returns |
|---|---|
(find-test name) |
the test object with that name (compared with eq), or NIL |
(remove-test name) |
true if the test existed, after unregistering it |
(clear-tests package-designator) |
unregisters every test defined in that package |
A test object answers to test-name, test-package, test-description,
test-source, test-timeout, test-tags, test-skip and test-serial-p.
You rarely need these; the runner and reporters use them.
Next: Assertions.