In addition to library units the following files are provided. Use them by including the file in your code with the include special form.
This file provides the let-string-start+end syntax defined in SRFI-13. See: 6.13.
This file provides a macro based unit testing facility based upon expectations concerning evaluations of expressions. These functions return tagged lists which contain the results of the test package, test case, or expectations evaluated(there are a few other types of results dealing with the gloss, todo, and skip macros detailed below). These result lists are wired together during evaluation to form a large heirarchical tree in memory. This result tree is then passed to either user defined functions which traverse the tree manipulating it in any way desired, or passed to a supplied (read: defined already in test-infrastructure.scm) function which manipulates it in a simple way usually producing human readable or html generated output. API functions to deal with the result types are supplied and the representation of the result is black boxed to the user. It is a violation of encapsulation to inspect the representation directly, and it may change unpredictably in the future.
This macro will evaluate in a left to right fashion the clauses inside it. Clauses can only be certain things, detailed below. All of the clauses are executed, except of course if you bail out of the test package with the escape procedure mechanism. Test packages may nest indefinitely.
[macro] (test-package MESSAGE DESTNAME TERMNAME CLAUSES)
[macro] (test-package MESSAGE DESTNAME TERMNAME (BINDINGS) CLAUSES)
[macro] (test-package MESSAGE DESTNAME TERMNAME (warn MESSAGE) CLAUSES)
[macro] (test-package MESSAGE DESTNAME TERMNAME (warn MESSAGE) (BINDINGS) CLAUSES)
MESSAGE can be any scheme object, though usually it is a string.
DESTNAME is an unquoted symbol for an automatic destructor object that gets called when the test package completes for any reason. This symbol is bound to a destructor object and is available to you in the CLAUSES section of the test package. See below for the description of the destructor object interface.
TERMNAME is an unquoted symbol for an escape procedure available in the body of the test package, usually, this escape procedure is passed to (terminate ...) which calls it for you and performs other tasks. It is not recommended to call the escape procedure directly.
(warn MESSAGE) allows you to specify a warning object, usually a string, that gets associated with the test package. The warn function name is actually a syntax reserved word in the macro.
BINDINGS are let-style bindings that you may create and exist in the lexical scope of the test package.
CLAUSES are uses of (test-case ...) macros along with (gloss ...), (todo ...), (skip ...), and (terminate ...) macros. While you may use the (expect-* ...) style macros directly in a test package, doing so is not recommended. If the expectation fails, the test package macro will continue evaluating until all clauses are evaluated or the escape procedure mechanism is activated. This is different than a test-case macro where upon discovery of a failed expectation, evaluation stops immediatly.
This macro will evaluate in a left to right fashion the clauses inside it stopping at the first failed expectation. Clauses can only be certain things as detailed below. You may also stop the execution of expectations if you bail out of the test case with the escape procedure mechanism. Test cases may NOT nest.
[macro] (test-case MESSAGE DESTNAME TERMNAME CLAUSES)
[macro] (test-case MESSAGE DESTNAME TERMNAME (BINDINGS) CLAUSES)
[macro] (test-case MESSAGE DESTNAME TERMNAME (warn MESSAGE) CLAUSES)
[macro] (test-case MESSAGE DESTNAME TERMNAME (warn MESSAGE) (BINDINGS) CLAUSES)
MESSAGE can be any scheme object, though usually it is a string.
DESTNAME is an unquoted symbol for an automatic destructor object that gets called when the test case completes for any reason. This symbol is bound to a destructor object and is available to you in the CLAUSES section of the test package. See below for the description of the destructor object interface.
TERMNAME is an unquoted symbol for an escape procedure available in the body of the test case, usually, this escape procedure is passed to (terminate ...) which calls it for you and performs other tasks. It is not recommended to call the escape procedure directly.
(warn MESSAGE) allows you to specify a warning object, usually a string, that gets associated with the test case. The warn function name is actually a syntax reserved word in the macro.
BINDINGS are let-style bindings that you may create and exist in the lexical scope of the test case.
CLAUSES are uses of (expect-* ...) macros along with (gloss ...), (todo ...), (skip ...), and (terminate ...) macros. It is important to note that upon discovery of a failed expectation, the test case stops its evaluation and returns with the previous successful, and including the failed, expectations.
An expectation at its core simply evaluates its arguments and check to see if it matches the expectation. The positive or negative result is encapsulated, along with other things such as the unevaluated expressions being checked and some messages supplied with each expectation into a particular type of black box object that one can query with the appropriate API calls(detailed below).
Expectations all have a descriptive message that can be bound to them, along with an optional warning syntax detailed below. A design decision was made to supply expectation macros for the usual types of expectations a user needs because this reduced the abstractness of an expectation into something more manageable. In a future release however, I will supply a special expectation macro where you may supply any predicate you wish along with a ``type tag'' of the predicate.
[macro] (expect-zero MESSAGE CLAUSE)
[macro] (expect-zero MESSAGE (warn MESSAGE) CLAUSE)
This expectation checks to see if the evaluated expression passed to it is numerically equal to the exact integer zero.
MESSAGE can be any scheme object, though usually it is a string.
(warn MESSAGE) allows you to specify a warning object, usually a string, that gets associated with the expectation. The warn function name is actually a syntax reserved word in the macro.
CLAUSE is a single expression which should return a exact or inexact integer.
[macro] (expect-nonzero MESSAGE CLAUSE)
[macro] (expect-nonzero MESSAGE (warn MESSAGE) CLAUSE)
This expectation checks to see if the evaluated expression passed to it is numerically not equal to the exact integer zero.
MESSAGE can be any scheme object, though usually it is a string.
(warn MESSAGE) allows you to specify a warning object, usually a string, that gets associated with the expectation. The warn function name is actually a syntax reserved word in the macro.
CLAUSE is a single expression which should return an exact or inexact integer.
[macro] (expect-true MESSAGE CLAUSE)
[macro] (expect-true MESSAGE (warn MESSAGE) CLAUSE)
This expectation checks to see if the evaluated expression passed to it is the value #t.
MESSAGE can be any scheme object, though usually it is a string.
(warn MESSAGE) allows you to specify a warning object, usually a string, that gets associated with the expectation. The warn function name is actually a syntax reserved word in the macro.
CLAUSE is a single expression which should return #t.
[macro] (expect-false MESSAGE CLAUSE)
[macro] (expect-false MESSAGE (warn MESSAGE) CLAUSE)
This expectation checks to see if the evaluated expression passed to it is the value #f.
MESSAGE can be any scheme object, though usually it is a string.
(warn MESSAGE) allows you to specify a warning object, usually a string, that gets associated with the expectation. The warn function name is actually a syntax reserved word in the macro.
CLAUSE is a single expression which should return #t.
[macro] (expect-eq? MESSAGE EXPECTED CLAUSE)
[macro] (expect-eq? MESSAGE (warn MESSAGE) EXPECTED CLAUSE)
This expectation checks to see if (eq? EXPECTED CLAUSE) is true.
MESSAGE can be any scheme object, though usually it is a string.
(warn MESSAGE) allows you to specify a warning object, usually a string, that gets associated with the expectation. The warn function name is actually a syntax reserved word in the macro.
EXPECTED is a single expression which is evaluated and represents the value the CLAUSE must be eq? to in order for this expectation to return a positive resullt.
CLAUSE is a single expression which, when evaluated must return an object where an eq? of this result and the EXPECTED expression is #t.
The result object this macro produce shall contain the unevaluated CLAUSE expression as a field, but not an unevaluated EXPECTED expression.
[macro] (expect-eqv? MESSAGE EXPECTED CLAUSE)
[macro] (expect-eqv? MESSAGE (warn MESSAGE) EXPECTED CLAUSE)
This expectation checks to see if (eqv? EXPECTED CLAUSE) is true.
MESSAGE can be any scheme object, though usually it is a string.
(warn MESSAGE) allows you to specify a warning object, usually a string, that gets associated with the expectation. The warn function name is actually a syntax reserved word in the macro.
EXPECTED is a single expression which is evaluated and represents the value the CLAUSE must be eqv? to in order for this expectation to return a positive resullt.
CLAUSE is a single expression which, when evaluated must return an object where an eqv? of this result and the EXPECTED expression is #t.
The result object this macro produce shall contain the unevaluated CLAUSE expression as a field, but not an unevaluated EXPECTED expression.
[macro] (expect-equal? MESSAGE EXPECTED CLAUSE)
[macro] (expect-equal? MESSAGE (warn MESSAGE) EXPECTED CLAUSE)
This expectation checks to see if (equal? EXPECTED CLAUSE) is true.
MESSAGE can be any scheme object, though usually it is a string.
(warn MESSAGE) allows you to specify a warning object, usually a string, that gets associated with the expectation. The warn function name is actually a syntax reserved word in the macro.
EXPECTED is a single expression which is evaluated and represents the value the CLAUSE must be equal? to in order for this expectation to return a positive resullt.
CLAUSE is a single expression which, when evaluated must return an object where an equal? of this result and the EXPECTED expression is #t.
The result object this macro produce shall contain the unevaluated CLAUSE expression as a field, but not an unevaluated EXPECTED expression.
[macro] (expect-near? MESSAGE EXPECTED TOL CLAUSE)
[macro] (expect-near? MESSAGE (warn MESSAGE) EXPECTED TOL CLAUSE)
This expectation checks to see if (< (abs (- EXPECTED CLAUSE)) TOL))) is true.
MESSAGE can be any scheme object, though usually it is a string.
(warn MESSAGE) allows you to specify a warning object, usually a string, that gets associated with the expectation. The warn function name is actually a syntax reserved word in the macro.
EXPECTED is a single expression which is evaluated and represents the value the CLAUSE must be ``near'' to in order for this expectation to return a positive resullt.
CLAUSE is a single expression which should return an inexact or exact number.
TOL is a single expression which, when evaluated must return a tolerance value(usually a small inexact number like .0001).
The result object this macro produce shall contain the unevaluated CLAUSE expression as a field, but not the unevaluated EXPECTED or TOL expression.
[macro] (expect-positive MESSAGE CLAUSE)
[macro] (expect-positive MESSAGE (warn MESSAGE) CLAUSE)
This expectation checks to see if the evaluated expression passed to it is a positive value greater than zero.
MESSAGE can be any scheme object, though usually it is a string.
(warn MESSAGE) allows you to specify a warning object, usually a string, that gets associated with the expectation. The warn function name is actually a syntax reserved word in the macro.
CLAUSE is a single expression which should return an inexact or exact number.
[macro] (expect-negative MESSAGE CLAUSE)
[macro] (expect-negative MESSAGE (warn MESSAGE) CLAUSE)
This expectation checks to see if the evaluated expression passed to it is a negative value less than zero.
MESSAGE can be any scheme object, though usually it is a string.
(warn MESSAGE) allows you to specify a warning object, usually a string, that gets associated with the expectation. The warn function name is actually a syntax reserved word in the macro.
CLAUSE is a single expression which should return an inexact or exact number.
Expectations, test cases, test packages, and helper macros(gloss, todo, etc) all return an object that contains the results and other various aspects of the action performed which ultimately get wired together to form the result tree. This collection of functions forming the rest of the test infrastructure API allows manipulation of these results in an abstracted way as to allow changing of the representation in the future.
If any of these API functions, except test-package-result?, are passed something that isn't a test package result object, they will return 'not-a-test-package-result.
[procedure] (test-package-result? RESULT)
If RESULT is a result object from the invocation
of a test package macro, then this function will return
#t. Otherwise, it will return #f.
[procedure] (test-package-result-result-ref RESULT)
Returns the boolean result associated with the test package RESULT
object.
[procedure] (test-package-result-message-ref RESULT)
Returns the message object associated with the test package RESULT
object.
[procedure] (test-package-result-exps-ref RESULT)
Returns the list of result objects associated with the test package
RESULT object.
[procedure] (test-package-result-warning? RESULT)
If a warning had been attached to this test package, this function
will return #t, otherwise it will be #f.
[procedure] (test-package-result-warning-ref RESULT)
If a warning had been attached to this test package, this function
will return the warning object supplied by the user, otherwise it
shall return '().
If any of these API functions, except test-case-result?, are passed something that isn't a test case result object, they will return 'not-a-test-case-result.
[procedure] (test-case-result? RESULT)
If RESULT is a result object from the invocation
of a test case macro, then this function will return
#t. Otherwise, it will return #f.
[procedure] (test-case-result-result-ref RESULT)
Returns the boolean result associated with the test case RESULT
object.
[procedure] (test-case-result-message-ref RESULT)
Returns the message object associated with the test case RESULT
object.
[procedure] (test-case-result-expectations-ref RESULT)
Returns the list of expctation result objects associated with the test
case RESULT object.
[procedure] (test-case-result-warning? RESULT)
If a warning had been attached to this test case, this function
will return #t, otherwise it will be #f.
[procedure] (test-case-result-warning-ref RESULT)
If a warning had been attached to this test case, this function
will return the warning object supplied by the user, otherwise it
shall return '().
These expectations all take the form of passing a single expression to them to see if they match some a priori expectation. If any of these API functions, except expect-result?, are passed something that isn't a single clause style expectation result object, they will return 'not-an-expect-result.
[procedure] (expect-result? RESULT)
If RESULT is a single clause style result object from
the invocation of an expectation macro, then this function will
return #t. Otherwise, it will return #f.
[procedure] (expect-result-result-ref RESULT)
Returns the boolean result associated with the single clause
style expectation RESULT object.
[procedure] (expect-result-specific-ref RESULT)
This retrives the ``specific'' field of a particular single clause
style expectation. For example, if you had a result object from
an invocation of a (expect-zero? "foobar" (- 1 1))
expectation, then the ``specific'' field of the expectation
result object will be the string "zero". Here is a
table describing what the ``specific'' fields are for each kind
of single clause style expectation:
|
[procedure] (expect-result-message-ref RESULT)
Returns the message object associated with the single clause
style expectation RESULT object.
[procedure] (expect-result-unevaled-ref RESULT)
Returns the unevaluated expression supplied to a single clause style
expectation macro.
[procedure] (expect-result-evaled-ref RESULT)
Returns the evaluated expression supplied to a single clause style
expectation macro.
[procedure] (expect-result-warning? RESULT)
If a warning had been attached to this expectation, this function
will return #t, otherwise it will be #f.
[procedure] (expect-result-warning-ref RESULT)
If a warning had been attached to this expectation, this function
will return the warning object supplied by the user, otherwise it
shall return '().
These expectations all take the form of passing a two expressions, the ``left hand side'' and the ``right hand side'' to them to see if they match some a priori equivalence. The left hand side is that which you expect the right hand side to be equivalent. If any of these API functions, except expect-equivalence-result?, are passed something that isn't a single clause style expectation result object, they will return 'not-an-expect-equivalence-result.
[procedure] (expect-equivalence-result? RESULT)
If RESULT is a comparison style result object from
the invocation of an expectation macro, then this function will
return #t. Otherwise, it will return #f.
[procedure] (expect-equivalence-result-result-ref RESULT)
Returns the boolean result associated with the comparison style
expectation RESULT object.
[procedure] (expect-equivalence-result-specific-ref RESULT)
This retrives the ``specific'' field of a particular equivalence
style expectation. For example, if you had a result object from
an invocation of a (expect-equal? "foobar" 0 (- 1 1))
expectation, then the ``specific'' field of the expectation
result object will be the string "equal". Here is a
table describing what the ``specific'' fields are for each kind
of equivalence style expectation:
|
[procedure] (expect-equivalence-result-message-ref RESULT)
Returns the message object associated with the equivalence
style expectation RESULT object.
[procedure] (expect-equivalence-result-lhs-evaled-ref RESULT)
Returns the evaluated ``left hand side'' expression supplied to
an equivalence style expectation.
[procedure] (expect-equivalence-result-rhs-unevaled-ref RESULT)
Returns the unevaluated ``right hand side'' expression supplied
to an equivalence style expectation.
[procedure] (expect-equivalence-result-rhs-evaled-ref RESULT)
Returns the evaluated ``right hand side'' expression supplied
to an equivalence style expectation.
[procedure] (expect-equivalence-result-warning? RESULT)
If a warning had been attached to this expectation, this function
will return #t, otherwise it will be #f.
[procedure] (expect-equivalence-result-warning-ref RESULT)
If a warning had been attached to this expectation, this function
will return the warning object supplied by the user, otherwise it
shall return '().
This is a specialized expectation which accepts three expressions and checks to see if the ``right hand side'' is within a ``tolerance'' of the ``left hand side''. There is only one expectation in the tolerance style currently. If any of these API functions, except expect-tolerance-result?, are passed something that isn't a tolerance style expectation result object, they will return 'not-an-expect-tolerance-result.
[procedure] (expect-tolerance-result? RESULT)
If RESULT is a tolerance style result object from
the invocation of an expectation macro, then this function will
return #t. Otherwise, it will return #f.
[procedure] (expect-tolerance-result-result-ref RESULT)
Returns the boolean result associated with the tolerance style
expectation RESULT object.
[procedure] (expect-tolerance-result-specific-ref RESULT)
This retrives the ``specific'' field of a particular tolerance
style expectation. For example, if you had a result object from
an invocation of a (expect-near? "foobar" 100 .01 100.001)
expectation, then the ``specific'' field of the expectation
result object will be the string "near". Here is a
table describing what the ``specific'' fields are for each kind
of tolerance style expectation:
|
[procedure] (expect-tolerance-result-message-ref RESULT)
Returns the message object associated with a tolerance
style expectation RESULT object.
[procedure] (expect-tolerance-result-lhs-evaled-ref RESULT)
Returns the evaluated ``left hand side'' expression supplied to
a tolerance style expectation.
[procedure] (expect-tolerance-result-lhs-tol-evaled-ref RESULT)
Returns the evaluated ``tolerance'' expression supplied to
a tolerance style expectation.
[procedure] (expect-tolerance-result-rhs-unevaled-ref RESULT)
Returns the unevaluated ``right hand side'' expression supplied
to a tolerance style expectation.
[procedure] (expect-tolerance-result-rhs-evaled-ref RESULT)
Returns the evaluated ``right hand side'' expression supplied
to a tolerance style expectation.
[procedure] (expect-tolerance-result-warning? RESULT)
If a warning had been attached to this expectation, this function
will return #t, otherwise it will be #f.
[procedure] (expect-tolerance-result-warning-ref RESULT)
If a warning had been attached to this expectation, this function
will return the warning object supplied by the user, otherwise it
shall return '().
These upcomming macros and functions allow the author of the test suite to better control both the execution flow of the test suite and ``decoration'' of the test suite with important information like things yet to do, or just plain documentation.
When executing in a test package or a test case, one might discover some catastrophic failue of such proportions that it is utterly impossible to continue executing the test case or test package. When that happens you can use the termination facility to exit the test case or test package. Of course, no more expressions will be evaluated in the scope of the termination. It is recommended that you use this method of terminating the test case or test package evaluation since it wraps some contextual information up into the termination result so you can figure out what happened(and where) later when analyzing the result tree.
When using the manipulation API for a terminate result, if you pass a result to one of these function that is not a terminate result, it will return 'not-a-terminate-result.
[procedure] (terminate TERMFUNC MESSAGE)
This is the recommended termination method for a test case or a test package.
TERMFUNC is the name of the termination procedure that you specified in a test case or test package. You may pass any test package or test case termination function available to you in the lexical scope in which you call this function. The termination will take effect in the scope of the created termination function.
MESSAGE can be any scheme object, though usually it is a string.
[procedure] (terminate-result? RESULT)
If RESULT is a termination result object from the
invocation of a termination function, then this function will
return #t. Otherwise, it will return #f.
[procedure] (terminate-result-result-ref RESULT)
Returns the boolean result associated with the termination
function RESULT object. This is currently hard coded to
be #f.
[procedure] (terminate-result-scope-ref RESULT)
The ``scope'' of the termination result is exactly the MESSAGE
parameter supplied to the test case or test package associated with the
TERMFUNC.
[procedure] (terminate-result-container-ref RESULT)
The ``container'' of the termination result is going to be
either 'test-package or 'test-case depending upon which the
TERMFUNC was associated.
[procedure] (terminate-result-message-ref RESULT)
Returns the message object associated with the termination
RESULT object.
The destructor object allows for you to create helper functions which clean up for you usually in case of aborting of a test case or package. For example, suppose you are testing whether or not file writing to a file works correctly in a test case, so, you'd perform an expectation to open the file, and then queue a function in the destructor to remove the file, and then perform the expectation of the write. If the write(or subsequent) expectation fails, then the test case will automatically invoke the helper cleanup function specified in the destructor object that removes the file.
NOTE: This API is still a little experimental in the sense that eventually he destructor object should return a typed result that contains the success of the individual destructor calls. But for now, it is functional for what it does. Also, be VERY CAREFUL that you specify the arguments to these API calls correctly since due to lambda functions not being comparable, this API cannot garauntee that a true destructor object name had been passed to it. So if you call one of the following API calls incorrectly, the behaviour will be undefined.
[procedure] (destructor-atexit! DESTNAME FUNC ARGS ...)
This will insert a promise to calculate the FUNC with the
supplied ARGS ... into a queue in the DESTNAME
destructor object. Multiple invocations of this API call will
continue to queue up (FUNC ARGS ...) promises indefinitely.
This function returns a special ignore type that is ignored
by the test infrastructure system.
[procedure] (destructor-activate! DESTNAME)
This function will call, in order of queueing, all the promises
embeded into this destructor object, and then delete the
queue. This function is ALWAYS called at the completion
of a test package or test case; so be careful that the destructor
object doesn't contain anything harmful. However, you may call
it yourself and if you do, it will execute all of the queued
promises and then clear itself. This function returns
a special ignore type that is ignored by the test
infrastructure system.
[procedure] (destructor-clear! DESTNAME)
This function completely removes all of the promises associated
with the destructor object DESTNAME. This function
returns a special ignore type that is ignored by the
test infrastructure system.
[procedure] (destructor-dump DESTNAME)
This function, mostly used for debugging purposes, prints out
a simple representation of the queued atexit functions to the
current port. This function returns a special ignore
type that is ignored by the test infrastructure system.
The purpose of the todo API is to allow the author of a test suite the ability to record into the result tree for later analysis that something still needs to be done. This way you can count/manipulate this information at a later date. Todo macro invocations can occur inside of test cases or test packages.
[macro] (todo MESSAGE)
[macro] (todo (warn WARNING) MESSAGE)
MESSAGE can be any scheme object, though usually it is a string.
(warn WARNING) allows you to specify a warning object, usually a string, that gets associated with the todo. The warn function name is actually a syntax reserved word in the macro.
[procedure] (todo-result? RESULT)
If RESULT is a todo result object from the
invocation of a todo macro, then this function will
return #t. Otherwise, it will return #f.
[procedure] (todo-result-message-ref RESULT)
Returns the message object associated with the todo
RESULT object.
[procedure] (todo-result-warning? RESULT)
If a warning had been attached to this todo, this function
will return #t, otherwise it will be #f.
[procedure] (todo-result-warning-ref RESULT)
If a warning had been attached to this todo, this function
will return the warning object supplied by the user, otherwise it
shall return '().
The purpose of the gloss API is to allow the author of a test suite the ability to record messages into the result tree purely for documentation purposes. Gloss macro invocations can occur inside of test cases or test packages.
[macro] (gloss MESSAGE)
[macro] (gloss (warn WARNING) MESSAGE)
MESSAGE can be any scheme object, though usually it is a string.
(warn WARNING) allows you to specify a warning object, usually a string, that gets associated with the gloss. The warn function name is actually a syntax reserved word in the macro.
[procedure] (gloss-result? RESULT)
If RESULT is a gloss result object from the
invocation of the gloss macro, then this function will
return #t. Otherwise, it will return #f.
[procedure] (gloss-result-message-ref RESULT)
Returns the message object associated with the gloss
RESULT object.
[procedure] (gloss-result-warning? RESULT)
If a warning had been attached to this gloss, this function
will return #t, otherwise it will be #f.
[procedure] (gloss-result-warning-ref RESULT)
If a warning had been attached to this gloss, this function
will return the warning object supplied by the user, otherwise it
shall return '().
The purpose of the skip API is to allow the author of a test suite to completely skip evaluation of a set of expresssions. Skip macro invocations can occur inside of test cases or test packages.
[macro] (skip MESSAGE CLAUSES)
[macro] (skip (warn WARNING) MESSAGE CLAUSES)
MESSAGE can be any scheme object, though usually it is a string.
(warn WARNING) allows you to specify a warning object, usually a string, that gets associated with the gloss. The warn function name is actually a syntax reserved word in the macro.
CLAUSES can be more than one expression(as in a lambda form) that does NOT get evaluated at any time.
[procedure] (skip-result? RESULT)
If RESULT is a skip result object from the
invocation of the skip macro, then this function will
return #t. Otherwise, it will return #f.
[procedure] (skip-result-message-ref RESULT)
Returns the message object associated with the skip
RESULT object. Hopefully, it was stated why this
set of clauses had been skipped.
[procedure] (skip-result-warning? RESULT)
If a warning had been attached to this skip, this function
will return #t, otherwise it will be #f.
[procedure] (skip-result-warning-ref RESULT)
If a warning had been attached to this skip, this function
will return the warning object supplied by the user, otherwise it
shall return '().
This section of the API just contains a single macro currently since it is considered a little experimental for now. The side effecting evaluates all of its arguments as in a (begin ...) form, it returns a result that is completely ignored by the system and unavailable to the output analysis code.
[macro] (side-effect CLAUSES)
This macro expands into a begin form the clauses in order and when it
finishes evaluating them, returns a result that is silently ignored by
the testing infrastructure system. Usually this is used in conjuction with
(set! ...) or with complicated situations where a lot of setup
work must happen for an expectation to be performed.
This section contains a few functions whose purpose is to simplify certain kinds of manipulations of result objects.
([procedure] (*-result? RESULTOBJ))
This function will return #t of RESULTOBJ is any kind of an
evaluated result object. Otherwise, it shall return #f.
([procedure] (*-result-ref RESULTOBJ))
This function will return the result of any kind of RESULTOBJ
passed to it if it is indeed a true result object. Otherwise, it
shall emit an error to the current port, and return #f.
([procedure] (all-testpackage-results-true? RESULTLIST))
This function takes the result of a call to
(test-package-result-result-ref PACKAGERESULTOBJ) and returns
#t if every single contained result in that list had been true, or #f
otherwise.
([procedure] (all-testcase-expectations-true? RESULTLIST))
This function takes the result of a call to
(test-case-result-result-ref CASERESULTOBJ) and returns
#t if every single contained result in that list had been true, or #f
otherwise.
Once a result tree has been evaluated and constructed in memory, what do you do with it? Well, you can do anything you want with it if you choose to write the analysis or output generation functions and pass it the evaluated result tree, and this is, in fact, encouraged. However, usually you just want to print out the tree in a human readable format so you can check things before the serious analysis code gets written. So, to save work for the test suite designer, a tiny API has been written to produce human readable output given a tree of results rooted in a single test package. Of course the single test package may have many other test packages and test cases embedded within it.
[procedure] (printnl CLAUSES)
This function will print all of the evaluated CLAUSES
in order with a newline at the end of it.
[procedure] (printinl INDENT CLAUSES)
This function will INDENT a number of spaces and then
print all of the evaluated CLAUSES in order with a
newline at the end of it.
[procedure] (output-style-human RESULTTREE)
This function will print out a human readable rendering of the
RESULTTREE and return the toplevel package result.
This section contains some simple examples of how to author test suites.
Here is a simple example:
(let ((result ;; output-style-human function requires a single test package ;; to encapsulate enverything. (test-package "Arithmetic Operators" pd pe (test-case "Testing '+'" d e (expect-equal "Adding two positive numbers" 2 (+ 1 1)) (expect-equal "Adding two negative numbers" -2 (+ -1 -1)) (expect-zero "Adding positive and negative" (+ -1 1))) (test-case "Testing '-'" d e (expect-zero "Subtracting two positive numbers" (- 1 1)) (expect-zero "Subtracting two negative numbers" (- -1 -1)) (expect-equal "Subtracting positive and negative" -2 (- -1 1)))))) (output-style-human result))
The above example, when evaluated, will produce some human readable output and the a #t value as the result of the top level package. The result variable contains the tree of evaluated expectations, test cases, and the package arranged in a hierarchy extremely similar to the nesting of the above macros. If you desire to manipulate the result tree yourself, you may use the various APIs to manipulate the various results. Please see the implementation of (output-style-human ...) (it isn't large) in the test-infrastructure.scm file to see an example of this.
The variables: pe, e are the escape functions you may use with the (teminate ...) function call if you wish to abort the above code somewhere.
The variables: pd, d allow use of a "destructor" object which allows you to run side effecting functions at the "finishing" point of the evaluation of the test case or test package. These functions are run no matter if the code succeeded correctly or not, so be careful to manage the destructor object carefully so you don't perform unwanted side effects. The names of the destructor objects you supply are lexically scoped in the bodies of the test case or test package.
Now, here is some example output that (output-style-human ...) might generate with the above testing code:
Begin Package: Arithmetic Operators Begin Test Case: Testing '+' Begin Expectation: Adding two positive numbers Expect equal Expected Value: 2 Unevaluated: (+ 1 1) Evaluated: 2 Result: #t End Expectation: Adding two positive numbers Begin Expectation: Adding two negative numbers Expect equal Expected Value: -2 Unevaluated: (+ -1 -1) Evaluated: -2 Result: #t End Expectation: Adding two negative numbers Begin Expectation: Adding positive and negative Expect zero Unevaluated: (+ -1 1) Evaluated: 0 Result: #t End Expectation: Adding positive and negative Result: #t End Test Case: Testing '+' Begin Test Case: Testing '-' Begin Expectation: Subtracting two positive numbers Expect zero Unevaluated: (- 1 1) Evaluated: 0 Result: #t End Expectation: Subtracting two positive numbers Begin Expectation: Subtracting two negative numbers Expect zero Unevaluated: (- -1 -1) Evaluated: 0 Result: #t End Expectation: Subtracting two negative numbers Begin Expectation: Subtracting positive and negative Expect equal Expected Value: -2 Unevaluated: (- -1 1) Evaluated: -2 Result: #t End Expectation: Subtracting positive and negative Result: #t End Test Case: Testing '-' Result: #t End Package: Arithmetic Operators #t