test-infrastructure

[Picture of an egg]

Description

Macro based unit-testing facility

Author

Peter Keller

Version

Requires

chicken 2.225+

Usage

(require-extension test-infrastructure)

This extension can currently only be used with the syntax-case (highlevel) macro system.

Download

test-infrastructure.egg

Documentation

This extension 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 hierarchical 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 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.

The term MESSAGE below means the name given to a test element. While this can be any Scheme object #f is interpreted as a missing name. Further, #f is assumed when a name is missing. Thus, the name of all un-named test elements is the same - #f.

The Immediate Test Macro API

This macro will evaluate in a left to right fashion the clauses inside it and output the results. The clauses are a sequence of (Expression Expectation) forms. A clause is evaluated as (expect-equal 'Expression Expectation Expression). For use in a REPL.

The results are not kept and no other forms are allowed in the body.

(macro) test-it

(test-it (EXPRESSION EXPECTED) ...)

The Quick Test Macro API

This macro will execute the test procedure and send the results to a stylist procedure. The specifiers can be used to select and de-select test packages, groups, cases, and expectations.

Do not de-select all, or omit to select least one, test packages or groups. Otherwise the result will be ill-formed.

The results are not kept.

(macro) test-apply

(test-apply [STYLER] [SPECIFIER ...] THUNK)

The Test Message Introspection API

Provides information on the tree structure of a test.

(macro) test-named-structure

(test-named-structure THUNK ...)
(procedure) walk-test-named-structure

(walk-test-named-structure PROCEDURE NAMED-STRUCTURE)

The Simple Test Package Macro API

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 group with the escape procedure mechanism. Note that a test group is a test package.

The destructor object name is destructor. The escape procedure name is escape. Each nesting will lexically shadow the previous such definitions of an outer test group.

(macro) test-group

(test-group [MESSAGE] [(BINDINGS)] CLAUSES)

The Test Package Macro API

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 groups and packages may nest indefinitely.

(macro) test-package

(test-package MESSAGE DESTNAME TERMNAME [(warn MESSAGE)] [(BINDINGS)] CLAUSES)

The Test Case Macro API

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

(test-case MESSAGE DESTNAME TERMNAME [(warn MESSAGE)] [(BINDINGS)] CLAUSES)

The Expectation Macro API

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.

Expectations are evaluated under an exception handler. An unexpected exception is treated as expectation failure. Note that only the CLAUSE expression evaluation traps exceptions. Any exceptions in setup or teardown expressions will not be caught by the test-infrastructure.

(macro) expect

(expect [MESSAGE] [(warn MESSAGE)] KIND PREDICATE CLAUSE)
(macro) expect-zero

(expect-zero [MESSAGE] [(warn MESSAGE)] CLAUSE)
(macro) expect-nonzero

(expect-nonzero [MESSAGE] [(warn MESSAGE)] CLAUSE)
(macro) expect-true

(expect-true [MESSAGE] [(warn MESSAGE)] CLAUSE)
(macro) expect-false

(expect-false [MESSAGE] [(warn MESSAGE)] CLAUSE)
(macro) expect-success

(expect-success [MESSAGE] [(warn MESSAGE)] CLAUSE)
(macro) expect-failure

(expect-failure [MESSAGE] [(warn MESSAGE)] CLAUSE)
(macro) expect-not-false

(expect-not-false [MESSAGE] [(warn MESSAGE)] CLAUSE)
(macro) expect-equiv

(expect-equiv [MESSAGE] [(warn MESSAGE)] KIND PREDICATE EXPECTED CLAUSE)
(macro) expect-eq

(expect-eq [MESSAGE] [(warn MESSAGE)] EXPECTED CLAUSE)
(macro) expect-eqv

(expect-eqv [MESSAGE] [(warn MESSAGE)] EXPECTED CLAUSE)
(macro) expect-equal

(expect-equal [MESSAGE] [(warn MESSAGE)] EXPECTED CLAUSE)
(macro) expect-values

(expect-values [MESSAGE] [(warn MESSAGE)] PREDICATE CLAUSE)
(macro) expect-values-eq

(expect-values-eq [MESSAGE] [(warn MESSAGE)] VALUES CLAUSE)
(macro) expect-values-eqv

(expect-values-eqv [MESSAGE] [(warn MESSAGE)] VALUES CLAUSE)
(macro) expect-values-equal

(expect-values-equal [MESSAGE] [(warn MESSAGE)] VALUES CLAUSE)
(macro) expect-near

(expect-near [MESSAGE] [(warn MESSAGE)] EXPECTED TOL CLAUSE)
(macro) expect-positive

(expect-positive [MESSAGE] [(warn MESSAGE)] CLAUSE)
(macro) expect-negative

(expect-negative [MESSAGE] [(warn MESSAGE)] CLAUSE)
(macro) expect-exception

(expect-exception [MESSAGE] [(warn MESSAGE)] EXN CLAUSE)
EXN : COND-EXN
    | SIMP-EXN
    | ()

SIMP-EXN : KINDKEY
         | (property KINDKEY PROP-EXPR ...)
         | (SIMP-EXN ...)

COND-EXN : (and EXN ...)
         | (or EXN ...)
         | (not EXN)

PROP-EXPR : COND-PROP-EXPR
          | SIMP-PROP-EXPR
          | ()

SIMP-PROP-EXPR : PROPKEY
               | (PROPKEY ...)
               | (PROPKEY VALUE)
               | (PREDICATE PROPKEY VALUE)

COND-PROP-EXPR : (and PROP-EXPR ...)
               | (or PROP-EXPR ...)
               | (not PROP-EXPR)

An example:

(test-case "exn1" d e (
    [exn1 (make-composite-condition
            (make-property-condition 'abc 'cbs "pbs")
            (make-property-condition 'foo 'bar "zip"))])

  (expect-exception "1" (foo abc) (signal exn1))

    ;; These are the same test, the 2nd has an explicit predicate
  (expect-exception "2" ((property foo (bar "zip"))
                         (property abc (cbs "pbs"))) (signal exn1))
  (expect-exception "3" ((property foo (equal? bar "zip"))
                         (property abc (equal? cbs "pbs"))) (signal exn1))
)
(macro) expect-ec

(expect-ec [MESSAGE] [(warn MESSAGE)] QUALIFIER ... EXPECTED [=> PREDICATE] CLAUSE)
(macro) expect-set!

(expect-set! ID EXPR)
(macro) expect-successful-failure

(expect-successful-failure EXPR)

Testeez-like API

A suite of synonyms for the expect-* macros. Note that the (warn WARNING) argument form is not supported. Here DESC is the same as MESSAGE, and EXPR is the same as CLAUSE.

(macro) test/zero

(test/zero [DESC] EXPR)

(macro) test/nonzero

(test/nonzero [DESC] EXPR)

(macro) test/true

(test/true [DESC] EXPR)

(macro) test/false

(test/false [DESC] EXPR)

(macro) test/success

(test/success [DESC] EXPR)

(macro) test/failure

(test/failure [DESC] EXPR)

(macro) test/positive

(test/positive [DESC] EXPR)

(macro) test/negative

(test/negative [DESC] EXPR)

(macro) test/not-false

(test/not-false [DESC] EXPR)

(macro) test/equiv

(test/equiv [DESC] EXPR EXPECTED PRED)

(macro) test/eq

(test/eq [DESC] EXPR EXPECTED)

(macro) test/eqv

(test/eqv [DESC] EXPR EXPECTED)

(macro) test/equal

(test/equal [DESC] EXPR EXPECTED)

(macro) test/near

(test/near [DESC] EXPR EXPECTED [TOL 0.0001])

(macro) test/values

(test/values [DESC] EXPR EXPECTED)

(macro) test/values-eq

(test/values-eq [DESC] EXPR EXPECTED)

(macro) test/values-eqv

(test/values-eqv [DESC] EXPR EXPECTED)

(macro) test/values-equal

(test/values-equal [DESC] EXPR EXPECTED)

(macro) test/exception

(test/exception [DESC] EXPR EXPECTED)

(macro) test/ec

(test/ec [DESC] QUALIFIER ... EXPECTED [=> PRED] EXPR)

Result Object API

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.

Test Package Result Object API

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?

(test-package-result? RESULT)
(procedure) test-package-result-result-ref

(test-package-result-result-ref RESULT)
(procedure) test-package-result-message-ref

(test-package-result-message-ref RESULT)
(procedure) test-package-result-exps-ref

(test-package-result-exps-ref RESULT)
(procedure) test-package-result-warning?

(test-package-result-warning? RESULT)
(procedure) test-package-result-warning-ref

(test-package-result-warning-ref RESULT)

Test Case Result Object API

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?

(test-case-result? RESULT)
(procedure) test-case-result-result-ref

(test-case-result-result-ref RESULT)
(procedure) test-case-result-message-ref

(test-case-result-message-ref RESULT)
(procedure) test-case-result-expectations-ref

(test-case-result-expectations-ref RESULT)
(procedure) test-case-result-warning?

(test-case-result-warning? RESULT)
(procedure) test-case-result-warning-ref

(test-case-result-warning-ref RESULT)

Expect Result Object API: Single Clause Style Expectation

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?

(expect-result? RESULT)
(procedure) expect-result-result-ref

(expect-result-result-ref RESULT)
(procedure) expect-result-specific-ref

(expect-result-specific-ref RESULT)
(procedure) expect-result-message-ref

(expect-result-message-ref RESULT)
(procedure) expect-result-unevaled-ref

(expect-result-unevaled-ref RESULT)
(procedure) expect-result-evaled-ref

(expect-result-evaled-ref RESULT)
(procedure) expect-result-warning?

(expect-result-warning? RESULT)
(procedure) expect-result-warning-ref

(expect-result-warning-ref RESULT)

Expect Result Object API: Equivalence Style Expectation

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?

(expect-equivalence-result? RESULT)
(procedure) expect-equivalence-result-result-ref

(expect-equivalence-result-result-ref RESULT)
(procedure) expect-equivalence-result-specific-ref

(expect-equivalence-result-specific-ref RESULT)
(procedure) expect-equivalence-result-message-ref

(expect-equivalence-result-message-ref RESULT)
(procedure) expect-equivalence-result-lhs-evaled-ref

(expect-equivalence-result-lhs-evaled-ref RESULT)
(procedure) expect-equivalence-result-rhs-unevaled-ref

(expect-equivalence-result-rhs-unevaled-ref RESULT)
(procedure) expect-equivalence-result-rhs-evaled-ref

(expect-equivalence-result-rhs-evaled-ref RESULT)
(procedure) expect-equivalence-result-warning?

(expect-equivalence-result-warning? RESULT)
(procedure) expect-equivalence-result-warning-ref

(expect-equivalence-result-warning-ref RESULT)

Expect Result Object API: Tolerance Style Expectation

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?

(expect-tolerance-result? RESULT)
(procedure) expect-tolerance-result-result-ref

(expect-tolerance-result-result-ref RESULT)
(procedure) expect-tolerance-result-specific-ref

(expect-tolerance-result-specific-ref RESULT)
(procedure) expect-tolerance-result-message-ref

(expect-tolerance-result-message-ref RESULT)
(procedure) expect-tolerance-result-lhs-evaled-ref

(expect-tolerance-result-lhs-evaled-ref RESULT)
(procedure) expect-tolerance-result-lhs-tol-evaled-ref

(expect-tolerance-result-lhs-tol-evaled-ref RESULT)
(procedure) expect-tolerance-result-rhs-unevaled-ref

(expect-tolerance-result-rhs-unevaled-ref RESULT)
(procedure) expect-tolerance-result-rhs-evaled-ref

(expect-tolerance-result-rhs-evaled-ref RESULT)
(procedure) expect-tolerance-result-warning?

(expect-tolerance-result-warning? RESULT)
(procedure) expect-tolerance-result-warning-ref

(expect-tolerance-result-warning-ref RESULT)

Various Helper API

These upcoming 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.

Termination API

When executing in a test package or a test case, one might discover some catastrophic failure 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

(terminate TERMFUNC MESSAGE)
(procedure) terminate-result?

(terminate-result? RESULT)
(procedure) terminate-result-result-ref

(terminate-result-result-ref RESULT)
(procedure) terminate-result-scope-ref

(terminate-result-scope-ref RESULT)
(procedure) terminate-result-container-ref

(terminate-result-container-ref RESULT)
(procedure) terminate-result-message-ref

(terminate-result-message-ref RESULT)

Destructor Object API

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 guarantee that a true destructor object name had been passed to it. So if you call one of the following API calls incorrectly, the behavior will be undefined.

(procedure) destructor-atexit!

(destructor-atexit! DESTNAME FUNC ARGS ...)
(procedure) destructor-activate!

(destructor-activate! DESTNAME)
(procedure) destructor-clear!

(destructor-clear! DESTNAME)
(procedure) destructor-dump

(destructor-dump DESTNAME)

Todo API

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

(todo MESSAGE) (todo (warn WARNING) MESSAGE)
(procedure) todo-result?

(todo-result? RESULT)
(procedure) todo-result-message-ref

(todo-result-message-ref RESULT)
(procedure) todo-result-warning?

(todo-result-warning? RESULT)
(procedure) todo-result-warning-ref

(todo-result-warning-ref RESULT)

Gloss API

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

(gloss MESSAGE) (gloss (warn WARNING) MESSAGE)
(procedure) gloss-result?

(gloss-result? RESULT)
(procedure) gloss-result-message-ref

(gloss-result-message-ref RESULT)
(procedure) gloss-result-warning?

(gloss-result-warning? RESULT)
(procedure) gloss-result-warning-ref

(gloss-result-warning-ref RESULT)

Skip API

The purpose of the skip API is to allow the author of a test suite to completely skip evaluation of a set of expressions. Skip macro invocations can occur inside of test cases or test packages.

(macro) skip

(skip MESSAGE CLAUSES) (skip (warn WARNING) MESSAGE CLAUSES)
(procedure) skip-result?

(skip-result? RESULT)
(procedure) skip-result-message-ref

(skip-result-message-ref RESULT)
(procedure) skip-result-warning?

(skip-result-warning? RESULT)
(procedure) skip-result-warning-ref

(skip-result-warning-ref RESULT)

Side Effect API

This section of the API 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

(side-effect CLAUSES)
(macro) test-continue?

(test-continue? BOOLEAN)
(macro) test-timing?

(test-timing? BOOLEAN)
(macro) test:set!

(test:set! VAR EXPR)

Miscellaneous API

This section contains a few functions whose purpose is to simplify certain kinds of manipulations of result objects.

(procedure) *-result?

(*-result? RESULT-OBJ)
(procedure) *-result-ref

(*-result-ref RESULT-OBJ)
(procedure) *-result-timing-values-ref

(*-result-timing-values-ref RESULT-OBJ)
(procedure) all-testpackage-results-true?

(all-testpackage-results-true? RESULT-LIST)
(procedure) all-testcase-expectations-true?

(all-testcase-expectations-true? RESULT-LIST)

Analysis of the Result Tree

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.

Statistics Generation API

(procedure) (stat-compute-statistics RESULT-TREE)
(procedure) (stat-packages-ref STATISTICS)
(procedure) (stat-package-warnings-ref STATISTICS)
(procedure) (stat-packages-passed-ref STATISTICS)
(procedure) (stat-packages-failed-ref STATISTICS)
(procedure) (stat-packages-timing-ref STATISTICS)
(procedure) (stat-packages-terminated-ref STATISTICS)
(procedure) (stat-cases-ref STATISTICS)
(procedure) (stat-case-warnings-ref STATISTICS)
(procedure) (stat-cases-passed-ref STATISTICS)
(procedure) (stat-cases-failed-ref STATISTICS)
(procedure) (stat-cases-timing-ref STATISTICS)
(procedure) (stat-cases-terminated-ref STATISTICS)
(procedure) (stat-all-expectations-ref STATISTICS)
(procedure) (stat-all-expectation-warnings-ref STATISTICS)
(procedure) (stat-all-expectations-passed-ref STATISTICS)
(procedure) (stat-all-expectations-failed-ref STATISTICS)
(procedure) (stat-all-expectations-timing-ref STATISTICS)
(procedure) (stat-single-expectations-ref STATISTICS)
(procedure) (stat-single-expectation-warnings-ref STATISTICS)
(procedure) (stat-single-expectations-passed-ref STATISTICS)
(procedure) (stat-single-expectations-failed-ref STATISTICS)
(procedure) (stat-single-expectations-timing-ref STATISTICS)
(procedure) (stat-tol-expectations-ref STATISTICS)
(procedure) (stat-tol-expectation-warnings-ref STATISTICS)
(procedure) (stat-tol-expectations-passed-ref STATISTICS)
(procedure) (stat-tol-expectations-failed-ref STATISTICS)
(procedure) (stat-tol-expectations-timing-ref STATISTICS)
(procedure) (stat-equiv-expectations-ref STATISTICS)
(procedure) (stat-equiv-expectation-warnings-ref STATISTICS)
(procedure) (stat-equiv-expectations-passed-ref STATISTICS)
(procedure) (stat-equiv-expectations-failed-ref STATISTICS)
(procedure) (stat-equiv-expectations-timing-ref STATISTICS)
(procedure) (stat-todos-ref STATISTICS)
(procedure) (stat-todo-warnings-ref STATISTICS)
(procedure) (stat-skips-ref STATISTICS)
(procedure) (stat-skip-warnings-ref STATISTICS)
(procedure) (stat-glosses-ref STATISTICS)
(procedure) (stat-gloss-warnings-ref STATISTICS)
(procedure) (stat-terminations-ref STATISTICS)

Output Generation API

These procedures help in the printing of test result reports. THUNK is a zero argument procedure to print a report. INDENT is the number of spaces to left indent. Use test:write-object when printing a data object.

(procedure) (test:output-apply THUNK [PORT|STRING|#t])
(procedure) (test:write-object OBJECT)
(procedure) (test:display-objects [OBJECT ...])
(procedure) (test:display-objects-newline [OBJECT ...])
(procedure) (test:display-indent INDENT)
(procedure) (test:display-indented-objects INDENT [OBJECT ...])
(procedure) (test:display-indented-objects-newline INDENT [OBJECT ...])

Output Style API

These functions will display a rendering of the RESULT-TREE and return the toplevel package result. The default destination is the (current-output-port). Otherwise the destination specifies how the output is targeted. A PORT destination will display to the port. A STRING destination will display to the specified file. Should the file exist the result is implementation dependent. A #t destination will return the output as a string.

(procedure) (output-style-human RESULT-TREE [PORT|STRING|#t])
(procedure) (output-style-html RESULT-TREE [PORT|STRING|#t])
(procedure) (output-style-compact RESULT-TREE [PORT|STRING|#t])
(procedure) (output-style-minimal RESULT-TREE [PORT|STRING|#t])

Example Usages of the Test Suite Infrastructure

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 everything.
  (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) in the test-infrastructure source to for an example of this.

The variables: pe, e are the escape functions you may use with the (terminate) procedure 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:

Test Package: Arithmetic Operators

  Test Case: Testing '+'

    Expectation: Adding two positive numbers
    Expect equal
         Expected: 2
      Unevaluated: (+ 1 1)
        Evaluated: 2
    Pass: Adding two positive numbers

    Expectation: Adding two negative numbers
    Expect equal
         Expected: -2
      Unevaluated: (+ -1 -1)
        Evaluated: -2
    Pass: Adding two negative numbers

    Expectation: Adding positive and negative
    Expect zero
      Unevaluated: (+ -1 1)
        Evaluated: 0
    Pass: Adding positive and negative

  Pass: Testing '+'

  Test Case: Testing '-'

    Expectation: Subtracting two positive numbers
    Expect zero
      Unevaluated: (- 1 1)
        Evaluated: 0
    Pass: Subtracting two positive numbers

    Expectation: Subtracting two negative numbers
    Expect zero
      Unevaluated: (- -1 -1)
        Evaluated: 0
    Pass: Subtracting two negative numbers

    Expectation: Subtracting positive and negative
    Expect equal
         Expected: -2
      Unevaluated: (- -1 1)
        Evaluated: -2
    Pass: Subtracting positive and negative

  Pass: Testing '-'

Pass: Arithmetic Operators

#t

Contributions

output-text-compact by Patrick Brannan.

License

Copyright (c) 2000-2005, Peter Keller - All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
conditions are met:

  Redistributions of source code must retain the above copyright notice, this list of conditions and the following
    disclaimer.
  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
    disclaimer in the documentation and/or other materials provided with the distribution.
  Neither the name of the author nor the names of its contributors may be used to endorse or promote
    products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

back