1.0 Introduction
2.0 The tester module API
2.1 Test Harness Variables
2.2 Test Harness Macros
3.0 Examples
Index
ANSI Common Lisp contains no functionality designed specifically for testing applications. Because testing is an essential part of application development, Franz Inc. is making public the test harness used internally for testing Allegro CL itself. (A test harness is a collection of macros and variables associated with testing, along with templates for test forms.)
The test harness facility will be part of the next major release of Allegro CL, and is available as a patch for Allegro CL 5.0.1. The patch, along with other patches providing new features (see the links in the Tech Corner[LINK] page) provides a preview of some of the technology available in the next major release of Allegro CL. The test harness facility is supported in ACL 5.0.1, and we encourage ACL customers to use it and to report problems and suggest improvements. Please address all correspondence (as with any technical issue, problem, or question) to support@franz.com.
To get the patch, evaluate (sys:update-allegro) in Allegro CL. This will automatically download and install all patches, including the one that implements the test harness facility (which will be in the downloaded file code/tester.fasl). Alternatively, you can manually download tester.fasl and tester.txt from the code/ directory of the patch directory (for the appropriate machine) from ftp://ftp.franz.com/pub/patches/5.0.1/.
Once the file tester.fasl is available, then (require :tester) is all that is needed to load it into Allegro CL.
All of the following symbols are exported from the :util.test package.
These macros wrap around a form to be tested and supply the expected value (for the test macro) or the expected behavior, which is encoded in the macro name (e.g. test-error). For example:
(test 1 (+ 0 1)) (testing that the result of (+ 0 1) is the fixnum 1)
(test-error (+ 1 "2")) (testing that an error is signaled when a string is passed as an argument to +)
Many more examples are given below.
with-tests wraps around a collection of test or test-* forms.
Note that many of the macros have fail-info and known-failure keyword arguments.
Arguments: expected-value test-form &key (test #'eql) multiple-values fail-info known-failure
Perform a single test. expected-value is the reference value for the test. test-form is a form that will produce the value to be compared (using the predicate that is the value of the test keyword argument) to expected-value. If the values are not the same, then a failure is logged; otherwise a success is logged.
The comparison is done with the predicate that is the value of the test keyword argument. The default value of test is eql. Other standard comparison functions include eq, equal, equalp, string=, string-equal, etc., and you may, of course, write your own predicate.
Normally, only the first return value from the test-form is considered, however if multiple-values is t, then all values returned from test-form are considered. If multiple-values is true, expected-values must be a list. If the length of the expected-value list differs from the number of returned values, the test will fail.
The value of the fail-info argument should be nil or a string. If a string, it is printed if the test fails, providing more information with a test failure. (Typical strings are "bug2127" and "can fail when network is slow".)
known-failure if non-nil, affects what is printed when the test fails or succeeds. Thus a failure is reported as "Test failed: known failure: ..." and a success as "Expected test failure for [...] did not occur."
Arguments: form &key announce catch-breaks fail-info known-failure (condition-type 'simple-error)
include-subtypes format-control format-arguments
Test that form signals an error. The order of evaluation of the arguments is keywords first, then form.
If announce is non-nil, then cause the error message to be printed.
If the catch-breaks is non-nil then consider a call to common-lisp:break an error.
The value of the fail-info argument should be nil or a string. If a string, it is printed if the test fails, providing more information with a test failure. (Typical strings are "bug2127" and "can fail when network is slow".)
known-failure if non-nil, affects what is printed when the test fails or succeeds. Thus a failure is reported as "Test failed: known failure: ..." and a success as "Expected test failure for [...] did not occur."
The value of condition-type must be a symbol naming a condition type (nil is not an acceptable value). The condition type is used to check against the signaled condition type. The test will fail if they do not match. Note: the default is simple-error so if this argument is unspecified, the test will fail if an error that is not a simple-error is signaled. If you want any error, specify the value of this argument error and the value of include-subtypes t.
include-subtypes, used with condition-type, can be used to match a condition to an entire subclass of the condition type hierarchy.
format-control and format-arguments can be used to check the error message itself. The comparison is done with equal.
Arguments: form &key announce catch-breaks fail-info known-failure
Test that form does not signal an error. The order of evaluation of the arguments is keywords first, then form.
If announce is non-nil, then cause the error message to be printed.
If the catch-breaks is non-nil then consider a call to common-lisp:break an `error'.
The value of the fail-info argument should be nil or a string. If a string, it is printed if the test fails, providing more information with a test failure. (Typical strings are "bug2127" and "can fail when network is slow".)
known-failure if non-nil, affects what is printed when the test fails or succeeds. Thus a failure is reported as "Test failed: known failure: ..." and a success as "Expected test failure for [...] did not occur."
Arguments: form &key fail-info known-failure
Test that form signals a warning. The order of evaluation of the arguments is keywords first, then form.
The value of the fail-info argument should be nil or a string. If a string, it is printed if the test fails, providing more information with a test failure. (Typical strings are "bug2127" and "can fail when network is slow".)
known-failure if non-nil, affects what is printed when the test fails or succeeds. Thus a failure is reported as "Test failed: known failure: ..." and a success as "Expected test failure for [...] did not occur."
Arguments: form &key fail-info known-failure
Test that form does not signal a warning. The order of evaluation of the arguments is keywords first, then form.
The value of the fail-info argument should be nil or a string. If a string, it is printed if the test fails, providing more information with a test failure. (Typical strings are "bug2127" and "can fail when network is slow".)
known-failure if non-nil, affects what is printed when the test fails or succeeds. Thus a failure is reported as "Test failed: known failure: ..." and a success as "Expected test failure for [...] did not occur."
Arguments: (&key (name "unnamed") &body body
The body is a list of test forms. At the end of execution of the body, a report is generated which summarizes successes and failures. with-tests binds *test-successes*, *test-errors*, and *test-unexpected-failures* to 0 before the execution of body and the printing of the results.
name is printed with the results -- "Begin <name> test", so "Begin unnamed test" if unspecified.
The following are simple examples using the test harness. The test forms themselves are trivial, and the purpose is to indicate the behavior of the test harness macros.
user(1): (require :tester) ; Fasl loading .../tester.fasl t user(2): (use-package :util.test) t user(3): (test 1 1) t user(4): (test 1 2) * * * UNEXPECTED TEST FAILURE * * * Test failed: 2 wanted: 1 got: 2 nil user(5): (defun foo (x) x) foo user(6): (test 1 (foo 1)) t user(7): (test 1 (foo 2)) * * * UNEXPECTED TEST FAILURE * * * Test failed: (foo 2) wanted: 1 got: 2 nil user(8): (setq *break-on-test-failures* t) t user(9): (test 1 (foo 2)) * * * UNEXPECTED TEST FAILURE * * * Test failed: (foo 2) wanted: 1 got: 2 Break: *break-on-test-failures* is non-nil.
Restart actions (select using :continue): 0: return from break. 1: Return to Top Level (an "abort" restart) 2: Abort #<process Initial Lisp Listener> [1c] user(10): :pop user(11): (setq *break-on-test-failures* nil) nil user(12): (test 1 (error "foo")) Error: foo
Restart actions (select using :continue): 0: Return to Top Level (an "abort" restart) 1: Abort #<process Initial Lisp Listener> [1] user(13): :pop user(14): (setq *error-protect-tests* t) t user(15): (test 1 (error "foo")) Condition type: simple-error Message: foo * * * UNEXPECTED TEST FAILURE * * * Test failed: (error "foo") Reason: an error (of type `simple-error') was detected. nil user(16): (setq *error-protect-tests* nil) nil user(17): *test-errors* 4 user(18): *test-successes* 2 user(19): (test 1 2 :known-failure t) Test failed: known failure: 2 wanted: 1 got: 2 nil user(20): (test 1 (foo 1) :known-failure t) Expected test failure for (foo 1) did not occur. nil user(21): (test 1 (foo 1) :known-failure t :fail-info "This is bug666.") Expected test failure for (foo 1) did not occur. Additional info: This is bug666. nil user(22): (test-error (error "foo")) t user(23): (test-no-error (error "foo")) * * * UNEXPECTED TEST FAILURE * * * Test failed: (error "foo") Reason: detected an unexpected error of type `simple-error'. nil user(24): (test-error (car '(10))) * * * UNEXPECTED TEST FAILURE * * * Test failed: (car '(10)) Reason: expected but did not detect an error of type `condition'. nil user(25): (test-no-error (car '(10))) t user(26): (test-warning (warn "foo")) t user(27): (test-no-warning (warn "foo")) * * * UNEXPECTED TEST FAILURE * * * Test failed: (warn "foo") wanted: no warning got: a warning nil user(28): (test-warning (car '(10))) * * * UNEXPECTED TEST FAILURE * * * Test failed: (car '(10)) wanted: a warning got: no warning nil user(29): (test-no-warning (car '(10))) t user(30): (test-error (error "foo: ~a" 10)) t user(31): (test-error (error "foo: ~a" 10) :format-control "foo: ~a") t user(32): (test-error (error "foo: ~a" 10) :format-control "foo: ~a" :format-arguments '(10)) t user(33): (test-error (error "foo: ~a" 10) :format-control "foo: ~a") * * * UNEXPECTED TEST FAILURE * * * Test failed: (error "foo: ~a" 10) Reason: the format-control was incorrect. wanted: "~1@<foo: ~a~:@>" got: "~1@<foo: ~a~:@>" nil user(34): (test-error (error "foo: ~a" 10) :format-control "foo: ~a" :format-arguments '(11)) * * * UNEXPECTED TEST FAILURE * * * Test failed: (error "foo: ~a" 10) Reason: the format-arguments were incorrect. wanted: (10) got: (11) nil user(35): (test-error (error "foo: ~a" 10) :condition-type 'condition :include-subtypes t) t user(36): (test-error (error "foo: ~a" 10) :condition-type 'simple-break :include-subtypes t) * * * UNEXPECTED TEST FAILURE * * * Test failed: (error "foo: ~a" 10) Reason: detected an incorrect condition type. wanted: simple-break got: #<standard-class simple-error> nil user(37): (test-error (break "foo: ~a" 10) :condition-type 'simple-break :include-subtypes t) Break: foo: 10 [condition type: simple-break]
Restart actions (select using :continue): 0: return from break. 1: Return to Top Level (an "abort" restart) 2: Abort #<process Initial Lisp Listener> [1c] user(38): :pop user(39): (test-error (break "foo: ~a" 10) :catch-breaks t :condition-type 'simple-break :include-subtypes t) t
Here are the macros and variables in this module.
*break-on-test-failures* [variable]
*error-protect-tests* [variable]
test [macro]
test-error [macro]
*test-errors* [variable]
test-no-error [macro]
test-no-warning [macro]
*test-successes* [variable]
*test-unexpected-failures* [variable]
test-warning [macro]
with-tests [macro]
Last updated on March 29, 2000 09:31:08 Pacific Standard Time
Copyright © 2023 Franz Inc., All Rights Reserved | Privacy Statement |