[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#71300: [PATCH v4] doc: Document SRFI 64.
From: |
Maxim Cournoyer |
Subject: |
bug#71300: [PATCH v4] doc: Document SRFI 64. |
Date: |
Wed, 02 Oct 2024 16:11:09 +0900 |
User-agent: |
Gnus/5.13 (Gnus v5.13) |
Hi Maxime,
Maxime Devos <maximedevos@telenet.be> writes:
>>> Based on this I believe it describes the specification.
>>
>>That's correct. It's been slightly modified in places where it said
>>things like "left to the implementation" and I was able to verify what
>>the current implementation in Guix does.
>
> I assume Guix->Guile.
>
> This modification of “left to the implementation” -> “what Guile does” is
> problematic, since it misleads readers into thinking this is the standard
> behaviour (it is after all named SRFI 64, not GRFI 64).
>
> “What Guile does” is also important information to have.
Yes, I agree. I think this is actually what I did, but my way to wording
of this above was not very good, and my memory fails. A diff of a
freshly "snarfed" [0] srfi-64.html (from its most recent commit) against
the documented submitted, which was hand-tuned:
diff -u /tmp/srfi-64-resnarfed.texi /tmp/srfi-64-documented.texi
--- /tmp/srfi-64-resnarfed.texi 2024-10-02 15:57:27.562406299 +0900
+++ /tmp/srfi-64-documented.texi 2024-10-02 15:58:57.798218571 +0900
@@ -1,71 +1,58 @@
-@node SRFI 64
-@subsection SRFI 64: A Scheme API for test suites
-@cindex SRFI 64
-
-
@node SRFI 64 Abstract
@subsubsection SRFI 64 Abstract
-
-This defines an API for writing @dfn{test suites}, to make it easy
-to portably test Scheme APIs, libraries, applications, and implementations.
-A test suite is a collection of @dfn{test cases} that execute
-in the context of a @dfn{test-runner}. This specification
-also supports writing new test-runners, to allow customization
-of reporting and processing the result of running test suites.
+This defines an API for writing @dfn{test suites}, to make it easy to
+portably test Scheme APIs, libraries, applications, and implementations.
+A test suite is a collection of @dfn{test cases} that execute in the
+context of a @dfn{test-runner}. This specification also supports
+writing new test-runners, to allow customization of reporting and
+processing the result of running test suites.
@node SRFI 64 Rationale
@subsubsection SRFI 64 Rationale
-
-The Scheme community needs a standard for writing test suites.
-Every SRFI or other library should come with a test suite.
-Such a test suite must be portable, without requiring any
-non-standard features, such as modules. The test suite implementation
-or "runner" need not be portable, but it is desirable that it be
-possible to write a portable basic implementation.
+The Scheme community needs a standard for writing test suites. Every
+SRFI or other library should come with a test suite. Such a test suite
+must be portable, without requiring any non-standard features, such as
+modules. The test suite implementation or "runner" need not be
+portable, but it is desirable that it be possible to write a portable
+basic implementation.
There are other testing frameworks written in Scheme, including
-@url{https://docs.racket-lang.org/rackunit/, RackUnit}However RackUnit is not
portable.
-It is also a bit on the verbose side.
-It would be useful to have a bridge between this framework and RackUnit
-so RackUnit tests could run under this framework and vice versa.
-There exists also at least one Scheme wrapper providing a Scheme interface
-to the ``standard''@url{https://www.junit.org/, JUnit} API for Java.
-It would be useful to have a bridge so that tests written using this
-framework can run under a JUnit runner.
-Neither of these features are part of this specification.
-
-This API makes use of implicit dynamic state, including an
-implicit ``test runner''. This makes the API convenient
-and terse to use, but it may be a little less elegant and
``compositional''than using explicit test objects, such as JUnit-style
frameworks.
-It is not claimed to follow either object-oriented or functional design
-principles, but I hope it is useful and convenient to use and extend.
+@url{https://docs.racket-lang.org/rackunit/, RackUnit}. However
+RackUnit is not portable. It is also a bit on the verbose side. It
+would be useful to have a bridge between this framework and RackUnit so
+RackUnit tests could run under this framework and vice versa. There
+exists also at least one Scheme wrapper providing a Scheme interface to
+the ``standard'' @url{https://www.junit.org/, JUnit} API for Java. It
+would be useful to have a bridge so that tests written using this
+framework can run under a JUnit runner. Neither of these features are
+part of this specification.
+
+This API makes use of implicit dynamic state, including an implicit
+``test runner''. This makes the API convenient and terse to use, but it
+may be a little less elegant and ``compositional'' than using explicit
+test objects, such as JUnit-style frameworks. It is not claimed to
+follow either object-oriented or functional design principles, but I
+hope it is useful and convenient to use and extend.
This proposal allows converting a Scheme source file to a
test suite by just adding a few macros. You don't have to
write the entire file in a new form, thus you don't have to
re-indent it.
-All names defined by the API start with the prefix @code{test-}All
function-like forms are defined as syntax. They may be implemented
-as functions or macros or built-ins. The reason for specifying them as
-syntax is to allow specific tests to be skipped without evaluating
sub-expressions, or for implementations
-to add features such as printing line numbers or catching exceptions.
-@c TODO: Review (delete/relocate) the following text (if any)
-@c orphaned by splicing the `(h1 Specification)' node.
-
-
-While this is a moderately complex specification,
-you should be able to write simple test suites after just reading the
-first few sections below. More advanced functionality, such
-as writing a custom test-runner, is at the end of the specification.
+All names defined by the API start with the prefix @samp{test-}. All
+function-like forms are defined as syntax. They may be implemented as
+functions or macros or built-ins. The reason for specifying them as
+syntax is to allow specific tests to be skipped without evaluating
+sub-expressions, or for implementations to add features such as printing
+line numbers or catching exceptions.
@node SRFI 64 Writing basic test suites
@subsubsection SRFI 64 Writing basic test suites
-
-Let's start with a simple example.
-This is a complete self-contained test-suite.
+Let's start with a simple example. This is a complete self-contained
+test-suite.
@lisp
;; Initialize and give a name to a simple testsuite.
@@ -81,73 +68,59 @@
(test-end "vec-test")
@end lisp
-This testsuite could be saved in its own source file.
-Nothing else is needed:
-We do not require any top-level forms, so it is easy
-to wrap an existing program or test to this form, without adding indentation.
-It is also easy to add new tests, without having to name individual
-tests (though that is optional).
-
-Test cases are executed in the context of a @dfn{test runner},
-which is a object that accumulates and reports test results.
-This specification defines how to create and use custom test runners,
-but implementations should also provide a default test runner.
-It is suggested (but not required) that loading the above
-file in a top-level environment will cause the
-tests to be executed using an implementation-specified default test runner,
-and @code{test-end} will cause a summary to be displayed
-in an implementation-specified manner.
+This testsuite could be saved in its own source file. Nothing else is
+needed: We do not require any top-level forms, so it is easy to wrap an
+existing program or test to this form, without adding indentation. It
+is also easy to add new tests, without having to name individual tests
+(though that is optional).
+
+Test cases are executed in the context of a @dfn{test runner}, which is
+a object that accumulates and reports test results. This specification
+defines how to create and use custom test runners, but implementations
+should also provide a default test runner. It is suggested (but not
+required) that loading the above file in a top-level environment will
+cause the tests to be executed using an implementation-specified default
+test runner, and @code{test-end} will cause a summary to be displayed in
+an implementation-specified manner.
@subsubheading Simple test-cases
+Primitive test cases test that a given condition is true. They may have
+a name. The core test case form is @code{test-assert}:
-Primitive test cases test that a given condition is true.
-They may have a name.
-The core test case form is @code{test-assert}:
-
+@deffn {Scheme Syntax} test-assert [test-name] expression
-@deffn {Scheme Procedure} test-assert [test-name] expression
-@c FIXME: Check deffn category and adjust '@end deffn' location
+This evaluates the @var{expression}. The test passes if the result is
+true; if the result is false, a test failure is reported. The test also
+fails if an exception is raised, assuming the implementation has a way
+to catch exceptions. How the failure is reported depends on the test
+runner environment. The @var{test-name} is a string that names the test
+case. (Though the @var{test-name} is a string literal in the examples,
+it is an expression. It is evaluated only once.) It is used when
+reporting errors, and also when skipping tests, as described below. It
+is an error to invoke @code{test-assert}if there is no current test
+runner.
@end deffn
+The following forms may be more convenient than using @code{test-assert}
+directly:
-This evaluates the @var{expression}The test passes if the result
-is true; if the result is false, a test failure is reported.
-The test also fails if an exception is raised, assuming the implementation
-has a way to catch exceptions.
-How the failure is reported depends on the test runner environment.
-The @var{test-name} is a string that names the test case.
-(Though the @var{test-name} is a string literal in the examples,
-it is an expression. It is evaluated only once.)
-It is used when reporting errors, and also when skipping tests,
-as described below.
-It is an error to invoke @code{test-assert}if there is no current test runner.
-
-The following forms may be more convenient than
-using @code{test-assert} directly:
-
-
-@deffn {Scheme Procedure} test-eqv [test-name] expected test-expr
-@c FIXME: Check deffn category and adjust '@end deffn' location
-@end deffn
-
+@deffn {Scheme Syntax} test-eqv [test-name] expected test-expr
This is equivalent to:
@lisp
-(test-assert [@var{test-name}] (eqv? @var{expected}@var{test-expr}))
+(test-assert [@var{test-name}] (eqv? @var{expected} @var{test-expr}))
@end lisp
-Similarly @code{test-equal} and @code{test-eq}are shorthand for
@code{test-assert} combined with
-@code{equal?} or @code{eq?}, respectively:
-
-
-@deffn {Scheme Procedure} test-equal [test-name] expected test-expr
-
-@deffnx {Scheme Procedure} test-eq [test-name] expected test-expr
-@c FIXME: Check deffn category and adjust '@end deffn' location
@end deffn
+Similarly @code{test-equal} and @code{test-eq} are shorthand for
+@code{test-assert} combined with @code{equal?} or @code{eq?},
+respectively:
+
+@deffn {Scheme Syntax} test-equal [test-name] expected test-expr
+@deffnx {Scheme Syntax} test-eq [test-name] expected test-expr
Here is a simple example:
@@ -155,56 +128,50 @@
(define (mean x y) (/ (+ x y) 2.0))
(test-eqv 4 (mean 3 5))
@end lisp
+@end deffn
For testing approximate equality of inexact reals
we can use @code{test-approximate}:
+@deffn {Scheme Syntax} test-approximate [test-name] expected test-expr error
-@deffn {Scheme Procedure} test-approximate [test-name] expected test-expr error
-@c FIXME: Check deffn category and adjust '@end deffn' location
-@end deffn
-
-
-This is equivalent to (except that each argument is only evaluated once):
+This is equivalent to (except that each argument is only evaluated
+once):
@lisp
(test-assert [test-name]
(and (>= test-expr (- expected error))
(<= test-expr (+ expected error))))
@end lisp
+@end deffn
@subsubheading Tests for catching errors
+We need a way to specify that evaluation @emph{should} fail. This
+verifies that errors are detected when required.
-We need a way to specify that evaluation @emph{should} fail.
-This verifies that errors are detected when required.
+@deffn {Scheme Syntax} test-error [[test-name] error-type] test-expr
+Evaluating @var{test-expr} is expected to signal an error. The kind of
+error is indicated by @var{error-type}.
-@deffn {Scheme Procedure} test-error [[test-name] error-type] test-expr
-@c FIXME: Check deffn category and adjust '@end deffn' location
-@end deffn
-
-
-Evaluating @var{test-expr} is expected to signal an error.
-The kind of error is indicated by @var{error-type}.
-
-If the @var{error-type} is left out, or it is
-@code{#t}, it means "some kind of unspecified error should be signaled".
-For example:
+If the @var{error-type} is left out, or it is @code{#t}, it means "some
+kind of unspecified error should be signaled". For example:
@lisp
(test-error #t (vector-ref '#(1 2) 9))
@end lisp
This specification leaves it implementation-defined (or for a future
-specification) what form @var{test-error} may take,
-though all implementations must allow @code{#t}Some implementations may support
-@url{https://srfi.schemers.org/srfi-35/srfi-35.html, SRFI-35's conditions},
-but these are only standardized for
-@url{https://srfi.schemers.org/srfi-36/srfi-36.html, SRFI-36's I/O
conditions}, which are seldom useful in test suites.
-An implementation may also allow implementation-specific
-``exception types''For example Java-based implementations may allow
-the names of Java exception classes:
+specification) what form @var{test-error} may take, though all
+implementations must allow @code{#t}. Some implementations may support
+@url{https://srfi.schemers.org/srfi-35/srfi-35.html, SRFI-35's
+conditions}, but these are only standardized for
+@url{https://srfi.schemers.org/srfi-36/srfi-36.html, SRFI-36's I/O
+conditions}, which are seldom useful in test suites. An implementation
+may also allow implementation-specific ``exception types''. For example
+Java-based implementations may allow the names of Java exception
+classes:
@lisp
;; Kawa-specific example
@@ -213,31 +180,23 @@
An implementation that cannot catch exceptions should skip
@code{test-error} forms.
+@end deffn
@subsubheading Testing syntax
-
-Testing syntax is tricky, especially if we want to
-check that invalid syntax is causing an error.
-The following utility function can help:
-
+Testing syntax is tricky, especially if we want to check that invalid
+syntax is causing an error. The following utility function can help:
@deffn {Scheme Procedure} test-read-eval-string string
-@c FIXME: Check deffn category and adjust '@end deffn' location
-@end deffn
-
-
-This function parses @var{string} (using @code{read})
-and evaluates the result.
-The result of evaluation is returned from @code{test-read-eval-string}An error
is signalled if there are unread characters after the
-@code{read} is done.
-For example:
-@code{(test-read-eval-string "(+ 3 4)")}@i{evaluates to}@code{7}.
-@code{(test-read-eval-string "(+ 3 4")}@i{signals an error}.
-@code{(test-read-eval-string "(+ 3 4) ")}@i{signals an error},
-because there is extra ``junk'' (@i{i.e.} a space) after the
-list is read.
+This function parses @var{string} (using @code{read}) and evaluates the
+result. The result of evaluation is returned from
+@code{test-read-eval-string}. An error is signalled if there are unread
+characters after the @code{read} is done. For example:
+@code{(test-read-eval-string "(+ 3 4)")} @i{evaluates to} @code{7}.
+@code{(test-read-eval-string "(+ 3 4")} @i{signals an error}.
+@code{(test-read-eval-string "(+ 3 4) ")} @i{signals an error}, because
+there is extra ``junk'' (@i{i.e.} a space) after the list is read.
The @code{test-read-eval-string} used in tests:
@@ -251,101 +210,81 @@
(test-equal 5 (test-read-eval-string "(+ 1 #;(* 2 3) 4)"))
(test-equal '(x z) (test-read-string "(list 'x #;'y 'z)"))
@end lisp
+@end deffn
@subsubheading Test groups and paths
-
A @dfn{test group} is a named sequence of forms containing testcases,
-expressions, and definitions.
-Entering a group sets the @dfn{test group name}; leaving a
-group restores the previous group name.
-These are dynamic (run-time) operations, and a group has no
-other effect or identity.
-Test groups are informal groupings: they are neither
-Scheme values, nor are they syntactic forms.
+expressions, and definitions. Entering a group sets the @dfn{test group
+name}; leaving a group restores the previous group name. These are
+dynamic (run-time) operations, and a group has no other effect or
+identity. Test groups are informal groupings: they are neither Scheme
+values, nor are they syntactic forms.
@c (More formal <q>test suite</q> values are introduced below.)
-
-
A test group may contain nested inner test groups.
The @dfn{test group path} is a list of the currently-active
(entered) test group names, oldest (outermost) first.
+@deffn {Scheme Syntax} test-begin suite-name [count]
-@deffn {Scheme Procedure} test-begin suite-name [count]
-@c FIXME: Check deffn category and adjust '@end deffn' location
-@end deffn
-
+A @code{test-begin} enters a new test group. The @var{suite-name}
+becomes the current test group name, and is added to the end of the test
+group path. Portable test suites should use a string literal for
+@var{suite-name}; the effect of expressions or other kinds of literals
+is unspecified.
-A @code{test-begin} enters a new test group.
-The @var{suite-name} becomes the current test group name,
-and is added to the end of the test group path.
-Portable test suites should use a string literal for @var{suite-name};
-the effect of expressions or other kinds of literals is unspecified.
-
-@b{Rationale:} In some ways using symbols would be preferable.
+@emph{Rationale:} In some ways using symbols would be preferable.
However, we want human-readable names, and standard Scheme does not
-provide a way to include spaces or mixed-case text in
-literal symbols.
+provide a way to include spaces or mixed-case text in literal symbols.
-The optional @var{count} must match the number of
-test-cases executed by this group.
-(Nested test groups count as a single test case for this count.)
-This extra test may be useful to catch cases where a test doesn't
-get executed because of some unexpected error.
+The optional @var{count} must match the number of test-cases executed by
+this group. (Nested test groups count as a single test case for this
+count.) This extra test may be useful to catch cases where a test
+doesn't get executed because of some unexpected error.
Additionally, if there is no currently executing test runner,
one is installed in an implementation-defined manner.
-
-
-@deffn {Scheme Procedure} test-end [suite-name]
-@c FIXME: Check deffn category and adjust '@end deffn' location
@end deffn
+@deffn {Scheme Syntax} test-end [suite-name]
A @code{test-end} leaves the current test group.
An error is reported if the @var{suite-name} does not
match the current test group name.
-@c If it does match an earlier
-@c name in the test group path, intervening groups are left.
-
+@c If it does match an earlier name in the test group path, intervening
+@c groups are left.
+Additionally, if the matching @code{test-begin}installed a new
+test-runner, then the @code{test-end} will uninstall it, after reporting
+the accumulated test results in an implementation-defined manner.
+@end deffn
-Additionally, if the matching @code{test-begin}installed a new test-runner,
then the @code{test-end}will uninstall it, after reporting the accumulated test
-results in an implementation-defined manner.
-
-@lisp
-(@b{test-group}@var{suite-name}@var{decl-or-expr} @dots{})
-@end lisp
+@deffn {Scheme Syntax} test-group suite-name decl-or-expr @dots{}
Equivalent to:
@lisp
-(if (not (test-to-skip% @var{suite-name}))
+(if (not (test-to-skip% (var suite-name)))
(dynamic-wind
- (lambda () (test-begin @var{suite-name}))
- (lambda () @var{decl-or-expr} @dots{})
- (lambda () (test-end @var{suite-name}))))
+ (lambda () (test-begin (var suite-name)))
+ (lambda () (var decl-or-expr) ...)
+ (lambda () (test-end (var suite-name)))))
@end lisp
This is usually equivalent to executing the @var{decl-or-expr}s
within the named test group. However, the entire group is skipped
if it matched an active @code{test-skip} (see later).
Also, the @code{test-end} is executed in case of an exception.
+@end deffn
@subsubheading Handling set-up and cleanup
+@deffn {Scheme Syntax} test-group-with-cleanup suite-name decl-or-expr @dots{}
cleanup-form
-
-@deffn {Scheme Procedure} test-group-with-cleanup suite-name decl-or-expr
@dots{} cleanup-form
-@c FIXME: Check deffn category and adjust '@end deffn' location
-@end deffn
-
-
-Execute each of the @var{decl-or-expr} forms in order
-(as in a @var{<body>}),
-and then execute the @var{cleanup-form}The latter should be executed even if
-one of a @var{decl-or-expr} forms raises an exception
-(assuming the implementation has a way to catch exceptions).
+Execute each of the @var{decl-or-expr} forms in order (as in a
+@var{<body>}), and then execute the @var{cleanup-form}. The latter
+should be executed even if one of a @var{decl-or-expr} forms raises an
+exception (assuming the implementation has a way to catch exceptions).
For example:
@@ -355,103 +294,77 @@
(do-a-bunch-of-tests f)
(close-output-port f)))
@end lisp
-
-@b{Erratum
note:}@url{https://github.com/scheme-requests-for-implementation/srfi-64/blob/4470ffdec71b1cf61633b664958a3ce5e6997710/srfi-64.html,
Earlier versions} had a non-working example.
-
-@c <h3>Test suites</h3>
-@c <p>
-@c <i>(Not sure how useful this is, given <code>test-group</code>).</i>
-@c <p>A <dfn>test suite</dfn> is a test group that can (and must) be
-@c executed explicitly.
-@c <pre>
-@c (test-suite <var>suite-name</var> <var>decl-or-expr</var> @dots{})
-@c </pre>
-@c <p>
-@c The <df>test suite path</dfn> is the list of names of currently
-@c running testsuites, from outermost (oldest) to innermost (newest).
-@c <p>A <code>test-suite</code> form is equivalent to:
-@c <pre>
-@c (test-suite-register <var>suite-name</var>
-@c (test-group <var>suite-name</var> <var>decl-or-expr</var> @dots{}))
-@c </pre>
-@c You can run previously registered test suite:
-@c <pre>
-@c (test-suite-run <var>suite-name</var>)
-@c </pre>
-
+@end deffn
@node SRFI 64 Conditonal test-suites and other advanced features
@subsubsection SRFI 64 Conditonal test-suites and other advanced features
-
The following describes features for controlling which tests to execute,
or specifying that some tests are @emph{expected} to fail.
@subsubheading Test specifiers
-
-Sometimes we want to only run certain tests, or we know that
-certain tests are expected to fail.
-A @dfn{test specifier} is one-argument function that takes a test-runner
-and returns a boolean. The specifier may be run before a test is performed,
-and the result may control whether the test is executed.
-For convenience, a specifier may also be a non-procedure value,
-which is coerced to a specifier procedure, as described below for
-@var{count} and @var{name}.
+Sometimes we want to only run certain tests, or we know that certain
+tests are expected to fail. A @dfn{test specifier} is one-argument
+function that takes a test-runner and returns a boolean. The specifier
+may be run before a test is performed, and the result may control
+whether the test is executed. For convenience, a specifier may also be
+a non-procedure value, which is coerced to a specifier procedure, as
+described below for @var{count} and @var{name}.
A simple example is:
@lisp
-(if @var{some-condition} (test-skip 2)) ;; skip next 2 tests
+(if (var some-condition) (test-skip 2)) ;; skip next 2 tests
@end lisp
-
@deffn {Scheme Procedure} test-match-name name
-The resulting specifier matches if the current test name (asreturned
by@code{test-runner-test-name}) is@code{equal?}toname.
+The resulting specifier matches if the current test name (as returned by
+@code{test-runner-test-name}) is @code{equal?} to @var{name}.
@end deffn
+@deffn {Scheme Syntax} test-match-nth n [count]
-@deffn {Scheme Procedure} test-match-nth n [count]
-
-This evaluates to a@emph{stateful}predicate: A counter keeps track ofhow many
times it has been called.The predicate matches then'th time it is
called(where@code{1}is the first time), andthe next
-@c FIXME: Check deffn category and adjust '@end deffn' location
+This evaluates to a @emph{stateful} predicate: A counter keeps track of
+how many times it has been called. The predicate matches the @var{n}'th
+time it is called (where @code{1} is the first time), and the next
+@samp{(- @var{count} 1)} times, where @var{count} defaults to @code{1}.
@end deffn
+@deffn {Scheme Syntax} test-match-any specifier @dots{}
-@c FIXME: Check deffn category and adjust '@end deffn' location
+The resulting specifier matches if any @var{specifier} matches. Each
+@var{specifier} is applied, in order, so side-effects from a later
+@var{specifier} happen even if an earlier @var{specifier} is true.
@end deffn
+@deffn {Scheme Syntax} test-match-all specifier @dots{}
-@c FIXME: Check deffn category and adjust '@end deffn' location
+The resulting specifier matches if each @var{specifier} matches. Each
+@var{specifier} is applied, in order, so side-effects from a later
+@var{specifier} happen even if an earlier @var{specifier} is false.
@end deffn
+@var{count} @i{(i.e. an integer)}
+Convenience short-hand for: @samp{(test-match-nth 1 @var{count})}.
-@var{count}@i{(i.e. an integer)}
-Convenience short-hand for: @code{(test-match-nth 1 @var{count})}.
-
-@var{name}@i{(i.e. a string)}
-Convenience short-hand for @code{(test-match-name @var{name})}.
+@var{name} @i{(i.e. a string)}
+Convenience short-hand for @samp{(test-match-name @var{name})}.
@subsubheading Skipping selected tests
-
In some cases you may want to skip a test.
+@deffn {Scheme Syntax} test-skip specifier
-@deffn {Scheme Procedure} test-skip specifier
-@c FIXME: Check deffn category and adjust '@end deffn' location
-@end deffn
-
-
-Evaluating @code{test-skip} adds the
-resulting @var{specifier}to the set of currently active skip-specifiers.
-Before each test (or @code{test-group})
-the set of active skip-specifiers are applied to the active test-runner.
-If any specifier matches, then the test is skipped.
+Evaluating @code{test-skip} adds the resulting @var{specifier} to the
+set of currently active skip-specifiers. Before each test (or
+@code{test-group}) the set of active skip-specifiers are applied to the
+active test-runner. If any specifier matches, then the test is skipped.
-For convenience, if the @var{specifier} is a string that
-is syntactic sugar for @code{(test-match-name @var{specifier})}For example:
+For convenience, if the @var{specifier} is a string that is syntactic
+sugar for @code{(test-match-name @var{specifier})}. For example:
@lisp
(test-skip "test-b")
@@ -459,7 +372,8 @@
(test-assert "test-b") ;; skipped
@end lisp
-Any skip specifiers introduced by a @code{test-skip}are removed by a following
non-nested @code{test-end}.
+Any skip specifiers introduced by a @code{test-skip} are removed by a
+following non-nested @code{test-end}.
@lisp
(test-begin "group1")
@@ -468,21 +382,16 @@
(test-end "group1") ;; Undoes the prior test-skip
(test-assert "test-a") ;; executed
@end lisp
+@end deffn
@subsubheading Expected failures
+Sometimes you know a test case will fail, but you don't have time to or
+can't fix it. Maybe a certain feature only works on certain platforms.
+However, you want the test-case to be there to remind you to fix it.
+You want to note that such tests are expected to fail.
-Sometimes you know a test case will fail, but you don't have time
-to or can't fix it. Maybe a certain feature only works on certain platforms.
-However, you want the test-case to be there
-to remind you to fix it. You want to note that
-such tests are expected to fail.
-
-
-@deffn {Scheme Procedure} test-expect-fail specifier
-@c FIXME: Check deffn category and adjust '@end deffn' location
-@end deffn
-
+@deffn {Scheme Syntax} test-expect-fail specifier
Matching tests (where matching is defined as in @code{test-skip})
are expected to fail. This only affects test reporting,
@@ -490,102 +399,95 @@
@lisp
(test-expect-fail 2)
-(test-eqv @dots{}) ;; expected to fail
-(test-eqv @dots{}) ;; expected to fail
-(test-eqv @dots{}) ;; expected to pass
+(test-eqv ...) ;; expected to fail
+(test-eqv ...) ;; expected to fail
+(test-eqv ...) ;; expected to pass
@end lisp
+@end deffn
@node SRFI 64 Test-runner
@subsubsection SRFI 64 Test-runner
-
-A @dfn{test-runner} is an object that runs a test-suite,
-and manages the state. The test group path, and the sets skip and
-expected-fail specifiers are part of the test-runner.
-A test-runner will also typically accumulate statistics about executed tests.
-
-
+A @dfn{test-runner} is an object that runs a test-suite, and manages the
+state. The test group path, and the sets skip and expected-fail
+specifiers are part of the test-runner. A test-runner will also
+typically accumulate statistics about executed tests,
@deffn {Scheme Procedure} test-runner? value
-True iff@code{value}is a test-runner object.
+True if and only if @var{value} is a test-runner object.
@end deffn
+@deffn {Scheme Parameter} test-runner-current
+@deffnx {Scheme Parameter} test-runner-current runner
-@deffn {Scheme Procedure} test-runner-current
-
-@deffnx {Scheme Procedure} test-runner-current runner
-
-Get or set the current test-runner.If an implementation supports parameter
objects(as in@url{https://srfi.schemers.org/srfi-39/srfi-39.html,
SRFI-39}),then@code{test-runner-current}can be a parameter
object.Alternatively,@code{test-runner-current}may be implementedas a macro or
functionthat uses a fluid or thread-local variable, or a plain global variable.
+Get or set the current test-runner.
@end deffn
-
@deffn {Scheme Procedure} test-runner-get
-Same as
-@c FIXME: Check deffn category and adjust '@end deffn' location
+Same as @code{(test-runner-current)}, but throws an exception if there
+is no current test-runner.
@end deffn
-
-
@deffn {Scheme Procedure} test-runner-simple
-Creates a new simple test-runner, that prints errors and a summaryon the
standard output port.
+Creates a new simple test-runner, that prints errors and a summary on
+the standard output port.
@end deffn
-
@deffn {Scheme Procedure} test-runner-null
-Creates a new test-runner, that does nothing with the test results.This is
mainly meant for extending when writing a custom runner.
+Creates a new test-runner, that does nothing with the test results.
+This is mainly meant for extending when writing a custom runner.
@end deffn
-Implementations @emph{may} provide other test-runners, perhaps
-a @code{(test-runner-gui)}.
-
-
@deffn {Scheme Procedure} test-runner-create
-Create a new test-runner. Equivalent to
-@c FIXME: Check deffn category and adjust '@end deffn' location
+Create a new test-runner. Equivalent to @samp{((test-runner-factory))}.
@end deffn
+@deffn {Scheme Parameter} test-runner-factory
+@deffnx {Scheme Parameter} test-runner-factory factory
-
-@deffn {Scheme Procedure} test-runner-factory
-
-@deffnx {Scheme Procedure} test-runner-factory factory
-
-Get or set the current test-runner factory.A factory is a zero-argument
function that creates a new test-runner.The default value
is@code{test-runner-simple},but implementations may provide a way to override
the default.As with@code{test-runner-current}, this may be a parameter
object,or use a per-thread, fluid, or global variable.
+Get or set the current test-runner factory. A factory is a
+zero-argument function that creates a new test-runner. The default
+value is @code{test-runner-simple}.
@end deffn
@subsubheading Running specific tests with a specified runner
-
-
@deffn {Scheme Procedure} test-apply [runner] specifier @dots{} procedure
-Callsprocedurewith no arguments using the specifiedrunneras the current
test-runner.Ifrunneris omitted,then
-@c FIXME: Check deffn category and adjust '@end deffn' location
+Calls @var{procedure} with no arguments using the specified @var{runner}
+as the current test-runner. If @var{runner} is omitted, then
+@code{(test-runner-current)} is used. (If there is no current runner,
+one is created as in @code{test-begin}.) If one or more
+@var{specifier}s are listed then only tests matching the
+@var{specifier}s are executed. A @var{specifier} has the same form as
+one used for @code{test-skip}. A test is executed if it matches any of
+the @var{specifier}s in the @code{test-apply} @emph{and} does not match
+any active @code{test-skip} specifiers.
@end deffn
+@deffn {Scheme Syntax} test-with-runner runner decl-or-expr @dots{}
-@c FIXME: Check deffn category and adjust '@end deffn' location
+Executes each @var{decl-or-expr} in order in a context where the current
+test-runner is @var{runner}.
@end deffn
-
@node SRFI 64 Test results
@subsubsection SRFI 64 Test results
-
Running a test sets various status properties in the current test-runner.
This can be examined by a custom test-runner,
or (more rarely) in a test-suite.
@subsubheading Result kind
-
Running a test may yield one of the following
status symbols:
+
@table @asis
@item @code{'pass}
The test passed, as expected.
@@ -601,70 +503,76 @@
@item @code{'skip}
The test was skipped.
-
@end table
-
@deffn {Scheme Procedure} test-result-kind [runner]
-Returns one of the above result codes from the most recent
tests.Returns@code{#f}if no tests have been run yet.If we've started on a new
test, but don't have a result yet,then the result kind is@code{'xfail}if the
test is expected to fail,@code{'skip}if the test is supposed to be
skipped,or@code{#f}otherwise.
+Returns one of the above result codes from the most recent tests.
+Returns @code{#f} if no tests have been run yet. If we've started on a
+new test, but don't have a result yet, then the result kind is
+@code{'xfail} if the test is expected to fail, @code{'skip} if the test
+is supposed to be skipped, or @code{#f} otherwise.
@end deffn
-
@deffn {Scheme Procedure} test-passed? [runner]
-True if the value of
-
-@deffnx {Scheme Procedure} test-result-kind [runner]
-
-is one of@code{'pass}or@code{'xpass}This is a convenient shorthand that might
be usefulin a test suite to only run certain tests if the previous test passed.
+True if the value of @samp{(test-result-kind [@var{runner}])} is one of
+@code{'pass} or @code{'xpass}. This is a convenient shorthand that
+might be useful in a test suite to only run certain tests if the
+previous test passed.
@end deffn
@subsubheading Test result properties
+A test runner also maintains a set of more detailed
+``result@tie{}properties'' associated with the current or most recent
+test. (I.e. the properties of the most recent test are available as
+long as a new test hasn't started.) Each property has a name (a symbol)
+and a value (any value). Some properties are standard or set by the
+implementation; implementations can add more.
-A test runner also maintains a set of more detailed ``result
properties''associated with the current or most recent test. (I.e. the
properties of the
-most recent test are available as long as a new test hasn't started.)
-Each property has a name (a symbol) and a value (any value).
-Some properties are standard or set by the implementation;
-implementations can add more.
-
+@deffn {Scheme Procedure} test-result-ref runner pname [default]
-@deffn {Scheme Procedure} test-result-ref runner ' pname [default]
-
-Returns the property value associated with thepnameproperty name.If there is
no value associated with@code{'pname}returndefault,or@code{#f}ifdefaultisn't
specified.
+Returns the property value associated with the @var{pname} property name
+(a symbol). If there is no value associated with @var{pname} return
+@var{default}, or @code{#f} if @var{default} isn't specified.
@end deffn
+@deffn {Scheme Syntax} test-result-set! runner pname value
-@deffn {Scheme Procedure} test-result-set! runner ' pname value
-
-Sets the property value associated with thepnameproperty name tovalueUsually
implementation code should call this function, but it may beuseful for a custom
test-runner to add extra properties.
+Sets the property value associated with the @var{pname} property name to
+@var{value}. Usually implementation code should call this function, but
+it may be useful for a custom test-runner to add extra properties.
@end deffn
+@deffn {Scheme Procedure} test-result-remove runner pname
-@deffn {Scheme Procedure} test-result-remove runner ' pname
-
-Remove the property with the name@code{'pname}.
+Remove the property with the name @var{pname}.
@end deffn
-
@deffn {Scheme Procedure} test-result-clear runner
-Remove all result properties.The implementation automatically
calls@code{test-result-clear}at the start of a@code{test-assert}and similar
procedures.
+Remove all result properties. The implementation automatically calls
+@code{test-result-clear} at the start of a @code{test-assert} and
+similar procedures.
@end deffn
-
@deffn {Scheme Procedure} test-result-alist runner
-Returns an association list of the current result properties.It is unspecified
if the result shares state with the test-runner.The result should not be
modified; on the other hand, the resultmay be implicitly modified by
future@code{test-result-set!}or@code{test-result-remove}calls.However,
a@code{test-result-clear}does not modify the returnedalist. Thus you
can``archive''result objects from previous runs.
+Returns an association list of the current result properties. It is
+unspecified if the result shares state with the test-runner. The result
+should not be modified; on the other hand, the result may be implicitly
+modified by future @code{test-result-set!} or @code{test-result-remove}
+calls. However, a @code{test-result-clear} does not modify the returned
+alist. Thus you can ``archive'' result objects from previous runs.
@end deffn
@subsubheading Standard result properties
-
The set of available result properties is implementation-specific.
However, it is suggested that the following might be provided:
@table @asis
+
@item @code{'result-kind}
The result kind, as defined previously.
This is the only mandatory result property.
@@ -691,121 +599,113 @@
@item @code{'actual-error}
The error value, if an error was signalled and it is known.
The actual error value is implementation-defined.
-
@end table
@node SRFI 64 Writing a new test-runner
@subsubsection SRFI 64 Writing a new test-runner
-
-This section specifies how to write a test-runner.
-It can be ignored if you just want to write test-cases.
+This section specifies how to write a test-runner. It can be ignored if
+you just want to write test-cases.
@subsubheading Call-back functions
-
These call-back functions are ``methods'' (in the object-oriented sense)
-of a test-runner. A method @code{test-runner-on-@var{event}}is called by the
implementation when @var{event} happens.
+of a test-runner. A method @code{test-runner-on-@var{event}} is called
+by the implementation when @var{event} happens.
-To define (set) the callback function for @var{event} use the following
expression.
-(This is normally done when initializing a test-runner.)
+To define (set) the callback function for @var{event} use the following
+expression. (This is normally done when initializing a test-runner.)
-@code{(test-runner-on-@var{event}! @var{runner}@var{event-function})}
+@code{(test-runner-on-@var{event}! @var{runner} @var{event-function})}
-An @var{event-function} takes a test-runner argument, and possibly other
arguments, depending on the @var{event}.
+An @var{event-function} takes a test-runner argument, and possibly other
+arguments, depending on the @var{event}.
To extract (get) the callback function for @var{event} do this:
-@code{(test-runner-on-@var{event}@var{runner})}
+@code{(test-runner-on-@var{event} @var{runner})}
-To extract call the callback function for @var{event} use the following
expression.
-(This is normally done by the implementation core.)
-@code{((test-runner-on-@var{event}@var{runner}) @var{runner}@var{other-args}
@dots{})}
+To extract call the callback function for @var{event} use the following
+expression. (This is normally done by the implementation core.)
+@samp{((test-runner-on-@var{event} @var{runner}) @var{runner}
+@var{other-args} @dots{})}.
The following call-back hooks are available.
-
@deffn {Scheme Procedure} test-runner-on-test-begin runner
-
@deffnx {Scheme Procedure} test-runner-on-test-begin! runner
on-test-begin-function
+@deffnx {Scheme Procedure} on-test-begin-function runner
-@deffnx {Scheme Procedure} on-test-begin-function runner
+The @var{on-test-begin-function} is called at the start of an
+individual testcase, before the test expression (and expected value) are
+evaluated.
-Theon-test-begin-functionis called at the start of anindividual testcase,
before the test expression (and expected value) areevaluated.
@end deffn
-
@deffn {Scheme Procedure} test-runner-on-test-end runner
-
@deffnx {Scheme Procedure} test-runner-on-test-end! runner on-test-end-function
+@deffnx {Scheme Procedure} on-test-end-function runner
-@deffnx {Scheme Procedure} on-test-end-function runner
-
-Theon-test-end-functionis called at the end of anindividual testcase, when the
result of the test is available.
+The @var{on-test-end-function} is called at the end of an
+individual testcase, when the result of the test is available.
@end deffn
-
@deffn {Scheme Procedure} test-runner-on-group-begin runner
-
@deffnx {Scheme Procedure} test-runner-on-group-begin! runner
on-group-begin-function
+@deffnx {Scheme Procedure} on-group-begin-function runner suite-name count
-@deffnx {Scheme Procedure} on-group-begin-function runner suite-name count
-
-Theon-group-begin-functionis called by a@code{test-begin},including at the
start of a@code{test-group}Thesuite-nameis a Scheme string,andcountis an
integer or@code{#f}.
+The @var{on-group-begin-function} is called by a @code{test-begin},
+including at the start of a @code{test-group}. The @var{suite-name} is
+a Scheme string, and @var{count} is an integer or @code{#f}.
@end deffn
-
@deffn {Scheme Procedure} test-runner-on-group-end runner
-
@deffnx {Scheme Procedure} test-runner-on-group-end! runner
on-group-end-function
+@deffnx {Scheme Procedure} on-group-end-function runner
-@deffnx {Scheme Procedure} on-group-end-function runner
-
-Theon-group-end-functionis called by a@code{test-end},including at the end of
a@code{test-group}.
+The @var{on-group-end-function} is called by a @code{test-end},
+including at the end of a @code{test-group}.
@end deffn
-
@deffn {Scheme Procedure} test-runner-on-bad-count runner
-
@deffnx {Scheme Procedure} test-runner-on-bad-count! runner
on-bad-count-function
+@deffnx {Scheme Procedure} on-bad-count-function runner actual-count
expected-count
-@deffnx {Scheme Procedure} on-bad-count-function runner actual-count
expected-count
-
-Called from@code{test-end}(before theon-group-end-functionis called) if
anexpected-countwas specified by the matching@code{test-begin}and
theexpected-countdoes not matchtheactual-countof tests actually executed or
skipped.
+Called from @code{test-end} (before the @var{on-group-end-function} is
+called) if an @var{expected-count} was specified by the matching
+@code{test-begin} and the @var{expected-count} does not match the
+@var{actual-count} of tests actually executed or skipped.
@end deffn
-
@deffn {Scheme Procedure} test-runner-on-bad-end-name runner
-
@deffnx {Scheme Procedure} test-runner-on-bad-end-name! runner
on-bad-end-name-function
+@deffnx {Scheme Procedure} on-bad-end-name-function runner begin-name end-name
-@deffnx {Scheme Procedure} on-bad-end-name-function runner begin-name end-name
-
-Called from@code{test-end}(before theon-group-end-functionis called) if
asuite-namewas specified, and it did not that thename in the
matching@code{test-begin}.
+Called from @code{test-end} (before the @var{on-group-end-function} is
+called) if a @var{suite-name} was specified, and it did not that the
+name in the matching @code{test-begin}.
@end deffn
-
@deffn {Scheme Procedure} test-runner-on-final runner
-
@deffnx {Scheme Procedure} test-runner-on-final! runner on-final-function
+@deffnx {Scheme Procedure} on-final-function runner
-@deffnx {Scheme Procedure} on-final-function runner
-
-Theon-final-functiontakes one parameter (a test-runner)and typically displays
a summary (count) of the tests.Theon-final-functionis called after called
theon-group-end-functioncorrespondiong to the outermost@code{test-end}The
default value is@code{test-on-final-simple}which writesto the standard output
port the number of tests of the various kinds.
+The @var{on-final-function} takes one parameter (a test-runner) and
+typically displays a summary (count) of the tests. The
+@var{on-final-function} is called after called the
+@var{on-group-end-function} correspondiong to the outermost
+@code{test-end}. The default value is @code{test-on-final-simple} which
+writes to the standard output port the number of tests of the various
+kinds.
@end deffn
-
-The default test-runner returned by@code{test-runner-simple}uses the following
call-back functions:
+The default test-runner returned by @code{test-runner-simple} uses the
+following call-back functions:
@deffn {Scheme Procedure} test-on-test-begin-simple runner
-
@deffnx {Scheme Procedure} test-on-test-end-simple runner
-
@deffnx {Scheme Procedure} test-on-group-begin-simple runner suite-name count
-
@deffnx {Scheme Procedure} test-on-group-end-simple runner
-
@deffnx {Scheme Procedure} test-on-bad-count-simple runner actual-count
expected-count
-
@deffnx {Scheme Procedure} test-on-bad-end-name-simple runner begin-name
end-name
You can call those if you want to write your own test-runner.
@@ -813,76 +713,71 @@
@subsubheading Test-runner components
-
-The following functions are for accessing the other components of a
test-runner.
-They would normally only be used to write a new test-runner or
-a match-predicate.
-
+The following functions are for accessing the other components of a
+test-runner. They would normally only be used to write a new
+test-runner or a match-predicate.
@deffn {Scheme Procedure} test-runner-pass-count runner
Returns the number of tests that passed, and were expected to pass.
@end deffn
-
@deffn {Scheme Procedure} test-runner-fail-count runner
Returns the number of tests that failed, but were expected to pass.
@end deffn
-
@deffn {Scheme Procedure} test-runner-xpass-count runner
Returns the number of tests that passed, but were expected to fail.
@end deffn
-
@deffn {Scheme Procedure} test-runner-xfail-count runner
Returns the number of tests that failed, and were expected to pass.
@end deffn
-
@deffn {Scheme Procedure} test-runner-skip-count runner
Returns the number of tests or test groups that were skipped.
@end deffn
-
@deffn {Scheme Procedure} test-runner-test-name runner
-Returns the name of the current test or test group, as a string.During
execution of@code{test-begin}this is the name of thetest group; during the
execution of an actual test, this is the nameof the test-case.If no name was
specified, the name is the empty string.
+Returns the name of the current test or test group, as a string. During
+execution of @code{test-begin} this is the name of the test group;
+during the execution of an actual test, this is the name of the
+test-case. If no name was specified, the name is the empty string.
@end deffn
-
@deffn {Scheme Procedure} test-runner-group-path runner
-A list of names of groups we're nested in, with the outermost group first.
+A list of names of groups we're nested in, with the outermost group
+first.
@end deffn
-
@deffn {Scheme Procedure} test-runner-group-stack runner
-A list of names of groups we're nested in, with the outermost group last.(This
is more efficient than@code{test-runner-group-path},since it doesn't require
any copying.)
+A list of names of groups we're nested in, with the outermost group
+last. (This is more efficient than @code{test-runner-group-path}, since
+it doesn't require any copying.)
@end deffn
-
@deffn {Scheme Procedure} test-runner-aux-value runner
-
@deffnx {Scheme Procedure} test-runner-aux-value! runner on-test
-Get or set the@code{aux-value}field of a test-runner.This field is not used by
this API or the@code{test-runner-simple}test-runner, but may be used by custom
test-runners to store extra state.
+Get or set the @code{aux-value} field of a test-runner. This field is
+not used by this API or the @code{test-runner-simple} test-runner, but
+may be used by custom test-runners to store extra state.
@end deffn
-
@deffn {Scheme Procedure} test-runner-reset runner
-Resets the state of therunnerto its initial state.
+Resets the state of the @var{runner} to its initial state.
@end deffn
@subsubheading Example
-
This is an example of a simple custom test-runner.
Loading this program before running a test-suite will install
it as the default test runner.
Diff finished. Wed Oct 2 15:59:15 2024
Looking at it more closely, it looks pretty much left alone. It's only
been re-flowed and some typos or extraneous comments fixed (I had
submitted a bunch of typo fixes to upstream but it seems I had missed to
send some).
I'm also attaching the two versions (original snarfed vs submitted) for
reference.
[0] To snarf it on your own, you can use the tool I had shared here:
https://lists.gnu.org/r/guile-devel/2023-12/msg00067.html
srfi-64-resnarfed.texi
Description: original
srfi-64-documented.texi
Description: documented
--
Thanks,
Maxim
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- bug#71300: [PATCH v4] doc: Document SRFI 64.,
Maxim Cournoyer <=