# (lispkit test)

Library `(lispkit test)` provides an API for writing uni tests. The API is largely compatible to similar APIs that are bundled with popular Scheme interpreters and compilers.

## Test groups

Tests are bundled in *test groups*. A test group contains actual *tests* comparing acual with expected values and *nested test groups*. Test groups may be given a *name* which is used for reporting on the testing progress and displaying aggregate test results for each test group.

The following code snippet illustrates how test groups are typically structured:

```scheme
(test-begin "Test group example")
(test "Sum of first 10 integers" 45 (apply + (iota 10)))
(test 64 (gcd 1024 192))
(test-approx 1.414 (sqrt 2.0))
(test-end)
```

This code creates a test group with name `Test group example`. The test group defines three tests, one verifying the result of `(apply + (iota 10))`, one testing `gcd` and one testing `sqrt`. When executed, the following output is shown:

```
╒═══════════════════════════════════════════════════════════════
│ Basic unit tests
└───────────────────────────────────────────────────────────────
[PASS] Sum of first 10 integers
[PASS] (gcd 1024 192)
[FAIL] (sqrt 2.0): expected 1.414 but received 1.414213562373095
┌───────────────────────────────────────────────────────────────
│ Basic unit tests
│ 3 tests completed in 0.001 seconds
│ 2 (66.66%) tests passed
│ 1 (33.33%) tests failed
╘═══════════════════════════════════════════════════════════════
```

Procedure `test-begin` opens a new test group. It is optionally given a test group name. Anonymous test groups (without name) are supported, but not encouraged as they make it more difficult to understand the testing output.

Special forms such as `test` and `test-approx` are used to compare expected values with actual result values. Expected values always preceed the actual values. Tests might also be given a name, which is used instead of the expression to test in the test report. `test`, `test-approx`, etc. need to be called in the context of a test group, otherwise the syntactical forms will fail. This is different from other similar libraries which often have an anonymous top-level test group implicitly.

Here is the structure of a more complicated testing setup which has a top-level test group `Library tests` and two nested test groups `Functionality A` and `Functionality B`.

```scheme
(test-begin "Library tests")
  (test-begin "Functionality A")
  (test ...)
  ...
  (test-end)
  (test-begin "Functionality B")
  ...
  (test-end)
(test-end)
```

The syntactic form `test-group` can be used to write small test groups more concisely. This code defines the same test group as above using `test-group`:

```scheme
(test-group "Library tests"
  (test-group "Functionality A"
    (test ...)
    ...)
  (test-group "Functionality B"
    (test ...)
    ...))
```

## Defining test groups

**(test-begin)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(test-begin&#x20;*****name*****)**

A new test group is opened via procedure `test-begin`. *name* defines a name for the test group. The name is primarily used in the test report to refer to the test group.

**(test-end)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(test-end&#x20;*****name*****)**

The currently open test group gets closed by calling procedure `test-end`. Optionally, for documentation and validation purposes, it is possible to provide *name*. If explicitly given, it has to match the name of the corresponding `test-begin` call in terms of `equal?`. When `test-end` is called, a summary gets printed listing stats such as passed/failed tests, the time it took to execute the tests in the group, etc.

**(test-exit)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(text-exit&#x20;*****obj*****)**

This procedure should be placed at the top-level of a test script. It raises an error if it is placed in the context of an open test group. If *obj* is provided and failures were encountered in the previously closed top-level test group, `test-exit` will exit the evaluation of the code by invoking `(exit obj)`.

**(test-group&#x20;*****name body ...*****)** <img src="/files/gEcsZuRGyhWFw4tM60U7" alt="" data-size="line">

`test-group` is a syntactical shortcut for opening and closing a new named test group. It is equivalent to:

```scheme
(begin
  (test-begin name)
  body ...
  (test-end))
```

**(test-group-failed-tests)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns the number of failed tests in the innermost active test group.

**(test-group-passed-tests)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns the number of passed tests in the innermost active test group.

**(failed-tests)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns the number of failed tests in all currently active test group.

**(passed-tests)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns the number of passed tests in all currently active test group.

## Comparing actual with expected values

**(test&#x20;*****exp tst*****)** <img src="/files/gEcsZuRGyhWFw4tM60U7" alt="" data-size="line">\
\&#xNAN;**(test&#x20;*****name exp tst*****)**

Main syntax for comparing the result of evaluating expression *tst* with the expected value *exp*. The procedure stored in parameter object *current-test-comparator* is used to compare the actual value with the expected value. *name* is supposed to be a string and used to report success and failure of the test. If not provided, the output of `(display tst)` is used as a name instead. `test` catches errors and prints informative failure messages, including the name, what was expected and what was computed. `test` is a convenience wrapper around `test-equal` that catches common mistakes.

**(test-equal&#x20;*****exp tst*****)** <img src="/files/gEcsZuRGyhWFw4tM60U7" alt="" data-size="line">\
\&#xNAN;**(test-equal&#x20;*****name exp tst*****)**\
\&#xNAN;**(test-equal&#x20;*****name exp tst eq*****)**

Compares the result of evaluating expression *tst* with the expected value *exp*. The procedure *eq* is used to compare the actual value with the expected value *exp*. If *eq* is not provided, the procedure stored in parameter object *current-test-comparator* is used as a default. *name* is supposed to be a string and it is used to report success and failure of the test. If not provided, the output of `(display tst)` is used as a name instead. `test-equal` catches errors and prints informative failure messages, including the name, what was expected and what was computed.

**(test-assert&#x20;*****tst*****)** <img src="/files/gEcsZuRGyhWFw4tM60U7" alt="" data-size="line">\
\&#xNAN;**(test-assert&#x20;*****name tst*****)**

`test-assert` asserts that the test expression *tst* is not false. It is a convenience wrapper around `test-equal`. *name* is supposed to be a string. It is used to report success and failure of the test. If not provided, the output of `(display tst)` is used as a name instead.

**(test-error&#x20;*****tst*****)** <img src="/files/gEcsZuRGyhWFw4tM60U7" alt="" data-size="line">\
\&#xNAN;**(test-error&#x20;*****name tst*****)**

`test-error` asserts that the test expression *tst* fails by raising an error. *name* is supposed to be a string. It is used to report success and failure of the test. If not provided, the output of `(display tst)` is used as a name instead.

**(test-approx&#x20;*****exp tst*****)** <img src="/files/gEcsZuRGyhWFw4tM60U7" alt="" data-size="line">\
\&#xNAN;**(test-approx&#x20;*****name exp tst*****)**

Compares the result of evaluating expression *tst* with the expected floating-point value *exp*. The procedure `approx-equal?` is used to compare the actual value with the expected flonum value *exp*. `approx-equal?` uses the parameter object `current-test-epsilon` to determine the precision of the comparison (the default is `0.0000001`). *name* is supposed to be a string. It is used to report success and failure of the test. If not provided, the output of `(display tst)` is used as a name instead. `test-approx` catches errors and prints informative failure messages, including the name, what was expected and what was computed.

**(test-not&#x20;*****tst*****)** <img src="/files/gEcsZuRGyhWFw4tM60U7" alt="" data-size="line">\
\&#xNAN;**(test-not&#x20;*****name tst*****)**

`test-not` asserts that the test expression *tst* is false. It is a convenience wrapper around `test-equal`. *name* is supposed to be a string. It is used to report success and failure of the test. If not provided, the output of `(display tst)` is used as a name instead.

**(test-values&#x20;*****exp tst*****)** <img src="/files/gEcsZuRGyhWFw4tM60U7" alt="" data-size="line">\
\&#xNAN;**(test-values&#x20;*****name exp tst*****)**

Compares the result of evaluating expression *tst* with the expected values *exp*. *exp* should be of the form `(values x ...)`. As opposed to `test` and `test-equal`, `test-values` works for multiple return values in a portable fashion. The procedure stored in parameter object *current-test-comparator* is used as a comparison procedure. *name* is expected to be a string.

## Test utilities

**current-test-comparator** <img src="/files/mK8eMQUj1oS8rq8TeU89" alt="" data-size="line">

Parameter object referring to the default comparison procedure for `test` and the `test-*` syntactical forms. By default, `current-test-comparator` refers to `equal?`.

**current-test-epsilon** <img src="/files/mK8eMQUj1oS8rq8TeU89" alt="" data-size="line">

Maximum difference allowed for inexact comparisons via procedure `approx-equal?`. By default, this parameter object is set to `0.0000001`.

**(approx-equal?&#x20;*****x y*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(approx-equal?&#x20;*****x y epsilon*****)**

Compares numerical value *x* with numerical value *y* and returns `#t` if *x* and *y* are approximately true. They are approximately true if *x* and *y* differ at most by *epsilon*. If *epsilon* is not provided, the value of parameter object `current-test-epsilon` is used as a default.

**(write-to-string&#x20;*****obj*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Writes value `obj` into a new string using procedure `write`, unless *obj* is a pair, in which case `write-to-string` interprets it as a Scheme expression and uses shortcut syntax for special forms such as `quote`, `quasiquote`, etc. This procedure is used to convert expressions into names of tests.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.lisppad.app/libraries/lispkit/lispkit-test.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
