Skip to content

Commit 89f5cec

Browse files
committed
Export and document a basic API for creating tests programmatically
This is fairly conservative in what is exported; it's just what I needed to create the mustache-spec-test-suite from the Mustache JSON spec test data.
1 parent 8f15094 commit 89f5cec

2 files changed

Lines changed: 119 additions & 4 deletions

File tree

documentation/source/reference.rst

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,3 +829,115 @@ Test Execution
829829
let locator = write-test-file("a/b/c.log", contents: "abc");
830830

831831
.. TODO(cgay): document the remaining exported names.
832+
833+
Programmatic API
834+
================
835+
836+
This section describes the APIs necessary for creating a test suite
837+
programmatically. This is sometimes useful if, for example, tests can be generated from
838+
available data or are more easily described in a format like JSON.
839+
840+
Create and :func:`register <register-component>` your test components and then call
841+
:func:`run-test-application` as usual.
842+
843+
.. class:: <component>
844+
:sealed:
845+
:abstract:
846+
847+
``<component>`` is a non-exported superclass of :class:`<runnable>` which is
848+
documented here only to show the init keywords inherited by tests, benchmarks, and
849+
suites.
850+
851+
:keyword name: The name of the component, an instance of :drm:`<string>`.
852+
853+
:keyword parent: The parent of this component, an instance of :class:`<component>`.
854+
855+
:keyword when:
856+
857+
A :drm:`<function>` to decide whether or not to execute the component during a test
858+
run. The function must accept one argument, the component and return a true value
859+
if the component should be executed or :drm:`#f` if it should be skipped.
860+
861+
.. class:: <runnable>
862+
:sealed:
863+
:abstract:
864+
865+
``<runnable>`` is a non-exported superclass of :class:`<benchmark>` and
866+
:class:`<test>` which is documented here only to show the init keywords inherited by
867+
those two classes.
868+
869+
:supers: `<component>`:class:
870+
871+
:keyword function:
872+
873+
The :drm:`<function>` that implements the test or benchmark. This function must
874+
accept no arguments and its return value, if any, is ignored.
875+
876+
:keyword expected-to-fail-test:
877+
878+
:drm:`#f` or a function that accepts no arguments and returns a true value to
879+
indicate that the test or benchmark is expected to fail. Useful if the test is
880+
only expected to fail on one operating system, for example.
881+
882+
:keyword expected-to-fail-reason:
883+
884+
A :drm:`<string>` describing why the test or benchmark is expected to fail. This is
885+
a convenience for the common case of a consistent failure on all platforms.
886+
887+
:discussion:
888+
889+
If either ``expected-to-fail-test`` or ``expected-to-fail-reason`` is specified,
890+
the runnable's result will be ``EXPECTED-TO-FAIL``. However, if the runnable's
891+
function returns without error (for example, it has no failed assertions) the
892+
result will be ``UNEXPECTED-SUCCESS``. If both keywords are specified,
893+
``expected-to-fail-test`` takes precedence.
894+
895+
.. class:: <benchmark>
896+
:sealed:
897+
:instantiable:
898+
899+
:supers: `<runnable>`:class:
900+
901+
See :class:`<runnable>` for a list of init keywords.
902+
903+
.. class:: <test>
904+
:sealed:
905+
:instantiable:
906+
907+
:supers: `<runnable>`:class:
908+
909+
See :class:`<runnable>` for a list of init keywords.
910+
911+
.. class :: <suite>
912+
:sealed:
913+
:instantiable:
914+
915+
:supers: `<component>`:class:
916+
917+
:keyword components: A :drm:`<sequence>` of child components (tests, benchmarks, or
918+
suites) for this suite. Each child component should specific this suite as its
919+
parent.
920+
921+
.. note:: Due to the bidirectional relationship between a suite and its children it
922+
may be convenient to supply an instance of `<stretchy-vector>`:drm: here
923+
so that the suite may be created first; it can then be used as the value
924+
of the ``parent:`` init keyword when creating the child components, and
925+
they can be added to the `<stretchy-vector>`:drm: afterwards.
926+
927+
:keyword setup-function:
928+
929+
See :macro:`suite-definer` for details.
930+
931+
:keyword cleanup-function:
932+
933+
See :macro:`suite-definer` for details.
934+
935+
See :class:`<component>` for additional init keywords.
936+
937+
.. function:: register-component
938+
939+
Register a component (a test, benchmark, or suite) with Testworks so that it will be
940+
found and executed during a test run. All components should be registered.
941+
942+
:signature: register-component ( *component* )
943+
:parameter component: An instance of :class:`<component>`.

library.dylan

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,13 @@ define module testworks
103103
interface-specification-class-instantiable?,
104104
make-test-instance,
105105
destroy-test-instance;
106+
107+
// API to create tests programmatically.
108+
create
109+
<benchmark>,
110+
<test>,
111+
<suite>,
112+
register-component;
106113
end module testworks;
107114

108115

@@ -150,22 +157,18 @@ define module %testworks
150157
*component*,
151158
compute-components,
152159
do-components,
153-
register-component,
154160
execute-component?,
155161
component-name,
156162
status-name;
157163

158164
// Tests and benchmarks
159165
export
160166
<runnable>,
161-
<benchmark>,
162-
<test>,
163167
test-function,
164168
test-tags;
165169

166170
// Suites
167171
export
168-
<suite>,
169172
make-suite, //--- Needed for macro hygiene problems
170173
suite-setup-function, suite-cleanup-function,
171174
suite-components;

0 commit comments

Comments
 (0)