6 Testing
All of the exports in this section are provided both by
redex/reduction-semantics (which includes
all non-GUI portions of Redex) and also exported by
redex (which includes all of Redex).
Tests to see if e1 is equal to e2.
(test-->> rel-expr option ... e1-expr e2-expr ...) |
|
option | | = | | #:cycles-ok | | | | | | #:equiv pred-expr |
|
|
|
Tests to see if the term
e1-expr,
reduces to the terms
e2-expr under
rel-expr,
using
pred-expr to determine equivalence. This test uses
apply-reduction-relation*, so it does not terminate
when the resulting reduction graph is infinite.
(test--> rel-expr option ... e1-expr e2-expr ...) |
|
option | | = | | #:equiv pred-expr |
|
|
|
Tests to see if the term e1-expr,
reduces to the terms e2-expr in a single rel-expr
step, using pred-expr to determine equivalence.
Examples: |
|
|
|
> (test--> R #:equiv mod2=? 7 1) |
FAILED :5.0 | expected: 1 | actual: 8 | actual: 7 |
|
> (test--> R #:equiv mod2=? 7 1 0) |
> (test-results) |
1 test failed (out of 2 total). |
Tests to see if the value of e matches the predicate p?.
Prints out how many tests passed and failed, and resets the
counters so that next time this function is called, it
prints the test results for the next round of tests.
Constructs a structure (recognized by
coverage?)
to contain per-case test coverage of the supplied metafunction
or reduction relation. Use with
relation-coverage and
covered-cases.
Returns
#t for a value produced by
make-coverage
and
#f for any other.
Redex populates the coverage records in
tracked (default
null),
counting the times that tests exercise each case of the associated metafunction
and relations.
Extracts the coverage information recorded in c, producing
an association list mapping names (or source locations, in the case of
metafunctions or unnamed reduction-relation cases) to application counts.
Examples: |
> (define-language empty-lang) |
|
|
|
'(("add" . 2) ("eval:10:0" . 1) ("zero" . 0)) |
'(("eval:9:0" . 2)) |
In its first form,
generate-term produces a random term matching
the given pattern (according to the given language). In its second,
generate-term produces a procedure for constructing the same.
This procedure expects
size-expr (below) as its sole positional
argument and allows the same optional keyword arguments as the first form.
The second form may be more efficient when generating many terms.
The argument size-expr bounds the height of the generated term
(measured as the height of its parse tree).
The optional keyword argument attempt-num-expr
(default 1) provides coarse grained control over the random
decisions made during generation; increasing attempt-num-expr
tends to increase the complexity of the result. For example, the expected
length of pattern-sequences increases with attempt-num-expr.
The random generation process does not actively consider the constraints
imposed by side-condition or _!_ patterns; instead,
it uses a “guess and check” strategy in which it freely generates
candidate terms then tests whether they happen to satisfy the constraints,
repeating as necessary. The optional keyword argument retries-expr
(default 100) bounds the number of times that
generate-term retries the generation of any pattern. If
generate-term is unable to produce a satisfying term after
retries-expr attempts, it raises an exception recognized by
exn:fail:redex:generation-failure?.
(redex-check language pattern property-expr kw-arg ...) |
|
kw-arg | | = | | #:attempts attempts-expr | | | | | | #:source metafunction | | | | | | #:source relation-expr | | | | | | #:retries retries-expr | | | | | | #:print? print?-expr |
|
|
|
Searches for a counterexample to
property-expr, interpreted
as a predicate universally quantified over the pattern variables
bound by
pattern.
redex-check constructs and tests
a candidate counterexample by choosing a random term
t that
matches
pattern then evaluating
property-expr
using the
match-bindings produced by
matching
t against
pattern.
redex-check generates at most attempts-expr (default 1000)
random terms in its search. The size and complexity of these terms increase with
each failed attempt.
returning a counterexample structure when the test reveals a counterexample,
returning #t when all tests pass, or
raising a exn:fail:redex:test when checking the property raises an exception.
When passed a metafunction or reduction relation via the optional #:source
argument, redex-check distributes its attempts across the left-hand sides
of that metafunction/relation by using those patterns, rather than pattern,
as the basis of its generation. It is an error if any left-hand side generates a
term that does not match pattern.
Examples: |
> (define-language empty-lang) |
> (random-seed 0) |
|
redex-check: counterexample found after 5 attempts: | ((1 0) (0)) |
|
|
redex-check: no counterexamples in 200 attempts |
|
() | (0) | (1 0) | redex-check: no counterexamples in 1 attempt (with each clause) |
|
Tests
relation as follows: for each case of
relation,
check-reduction-relation generates
attempts random
terms that match that case’s left-hand side and applies
property
to each random term.
This form provides a more convenient notation for
when relation is a relation on L with n rules.
(check-metafunction metafunction property kw-args ...) |
|
kw-arg | | = | | #:attempts attempts-expr | | | | | | #:retries retries-expr |
|
|
|
Recognizes the exceptions raised by
generate-term,
redex-check, etc. when those forms are unable to produce
a term matching some pattern.
Debugging PLT Redex Programs
It is easy to write grammars and reduction rules that are
subtly wrong and typically such mistakes result in examples
that just get stuck when viewed in a traces window.
The best way to debug such programs is to find an expression
that looks like it should reduce but doesn’t and try to find
out what pattern is failing to match. To do so, use the
redex-match special form, described above.
In particular, first ceck to see if the term matches the
main non-terminal for your system (typically the expression
or program nonterminal). If it does not, try to narrow down
the expression to find which part of the term is failing to
match and this will hopefully help you find the problem. If
it does match, figure out which reduction rule should have
matched, presumably by inspecting the term. Once you have
that, extract a pattern from the left-hand side of the
reduction rule and do the same procedure until you find a
small example that shoudl work but doesn’t (but this time
you might also try simplifying the pattern as well as
simplifying the expression).