srfi.252
- Property testing ¶Property testing is to feed random input to a component to be tested and see if it satisfies certain properties hold. The method was made popular with Haskell’s QuickCheck.
This module provides two groups of APIs; one for running property tests, and another for generating random input.
The test procedures are integrated with gauche.test
(see gauche.test
- Unit Testing). The SRFI is designed to be used with
SRFI-64 (see srfi.64
- A Scheme API for test suites); in Gauche, you can
run them with either of modules.
The random input generators are built on top of data.random
(see data.random
- Random data generators). They are provided for
the convenience; you can use any generator to create input feed.
[SRFI-252]{srfi.252
}
Calls property-check over the arguments generated by
the generators in generator-list as many times as runs.
property-check is an expression that evaluates to
a procedure accepts input, and returns
#t
if the property is satisfied, #f
if not.
The input is fed from generators listed in generator-list;
it must have as many generators as the number of arguments
property-check accepts.
The optional argument runs must be a nonnegative exact integer to specify how many times property-check should be run. If omitted, the system default is used, which is 30 in Gauche. The default runs may be changed in future.
Test-property
is the basic one; the test passes when every
property-check invocation returns true.
Test-property-expect-fail
, on the other hand, passes
when every property-check returns false (thus, expected failure).
Test-property-skip
does not run property-check, just
counts runs attempts as skipped tests.
Test-property-error
expects all invocations of property-check
raises an error.
Finally, test-property-error
and
test-property-error-type
expect all property-check invocations
raise an error. Additionally, test-property-error-type
expects the raised error is of type error-type,
which should be a condition type.
This SRFI is designed to be used with SRFI-64, but you can use these
directly with gauche.test
without loading srfi.64
.
[SRFI-252]{srfi.252
}
Returns a SRFI-64 test runner object specialized for property testing.
In Gauche, this simply returns SRFI-64 simple runner, but other
implementations may have some additional features. It is recommended
that portable code sets the runner created with this procedure
before calling property test procedures.
These are procedures that create generators of specific types.
You can find similar generator procedurs in data.random
(see data.random
- Random data generators)
and srfi.194
(see srfi.194
- Random data generators (SRFI)),
but the procedures here creates generators with one specific
property suitable for testing: They start generating certain
pre-defined values–typical, or boundary values–before generating
random values.
All created generators captures the value of parameter
random-data-random-source
(see data.random
- Random data generators) when created.
If you want to have reproducible results, you can provide your own
random source.
[SRFI-252]{srfi.252
}
Returns a generator that yields #t
and #f
, then
a random boolean values in equal probability.
See also booleans$
in data.random
(see data.random
- Random data generators).
[SRFI-252]{srfi.252
}
Returns a generator that yields an empty bytevector #u8()
first,
then bytevectors of random length and random content subsequently.
In Gauche, it is realized as follows (see data.random
- Random data generators,
for sequences-of
and integers$
).
The constant sequence-max-size
is currently 33 but may be
changed.
(gcons* '#u8() (sequences-of <u8vector> (integers$ sequence-max-size) (integers$ 256))))
[SRFI-252]{srfi.252
}
Returns a character generator that yields #\null
, then
random characters subsequently. Currently we sample
charactres uniformly from the entire Unicode range, but that
causes most of the characters to be very infrequently used ones.
We might change it in future.
See also chars$
in data.random
(see data.random
- Random data generators).
[SRFI-252]{srfi.252
}
Returns a string generator that yields an empty string ""
,
then strings of random length and random content subsequently.
In Gauche, it is realized as follows (see data.random
- Random data generators,
for strings-of
and integers$
).
The constant sequence-max-size
is currently 33 but may be
changed.
(gcons* "" (strings-of (integers$ sequence-max-size) (chars$ char-set:full)))
Note that the chracters are sampled uniformly from the entire Unicode range, which causes almost all strings to consist of very infrequently used characters. We might address this in future.
[SRFI-252]{srfi.252
}
Returns a symbol generator that yields a symbol whose name
is empty (||
), then symbols of random length and
random content subsequently. It is basically
(gmap string->symbol (string-generator))
.
Note that the chracters are sampled uniformly from the entire Unicode range, which causes almost all symbols to consist of very infrequently used characters. We might address this in future.
[SRFI-252]{srfi.252
}
Returns a generator that yields the following inexact complex
numbers, followed by random complex numbers.
0.0 -0.0 0.5 -0.5 1.0 -1.0 0.0+1.0i 0.0-1.0i -0.0+1.0i -0.0-1.0i 0.5+0.5i 0.5-0.5i -0.5+0.5i -0.5-0.5i 1.0+1.0i 1.0-1.0i -1.0+1.0i -1.0-1.0i +inf.0+inf.0i +inf.0-inf.0i -inf.0+inf.0i -inf.0-inf.0i +nan.0+nan.0i +inf.0 -inf.0 +nan.0
Note: SRFI specifies complex-generator
to return
both exact and inexact complex numbers if the implementation supports
them. Gauche doesn’t have exact complex numbers, so it is the
same as inexact-complex-generator
.
In Gauche, a random complex number is created by
uniformly sampled finite flonums for real and imaginary parts.
Note that “uniformly sampled finite flonums” are not the same
as “uniformly sampled real numbers”; See finite-flonums$
for the details (see data.random
- Random data generators).
[SRFI-252]{srfi.252
}
Gauche does not support exact complex numbers, and these procedures
raise an error when called.
[SRFI-252]{srfi.252
}
Return generators that yields integers, exact integers,
and inexact integers, respectively.
The exact integer generator always yield 0
, 1
, and -1
at the beginning, then random integers follow.
The inexact integer generator always yield 0.0
, -0.0
,
1.0
, and -1.0
at the beginning, then random integers follow.
The general integer generator created by integer-generator
samples evenly from an exact integer genratgor and an inexact
integer generator.
Since the range of exact integers is only bounded by the memory, uniform sampling from the entire possible range is infeasible; almost all samples would become a huge integer. Instead, we split integer range into 3: relatively small integers, fixnums, and bignums, and sample evenly from these three generators. Small integers and fixnums are sampled uniformly within its range, and bignums are sampled according to the power law; so, we see a lot more bignums closer to fixnum range, with occasional really big numbers sprinkled in.
[SRFI-252]{srfi.252
}
Return generators that yields rational numbers, exact rational numbers,
and inexact rational numbers, respectively.
The exact rational number generator yields
0
, 1
, -1
, 1/2
, and -1/2
at
the beginning, then generate (/ a b)
where a
, b
are generated in the same way as exact-integer-generator
’s
distribution, except 0 is excluded from b
.
The inexact rational number generator yields
0.0
, -0.0
, 0.5
, =0.5
, 1.0
, and -1.0
at the beginning, then proceed to generate random inexact rational numbers.
In Gauche, inexact rational numbers are finite flonums, and we uniformly
samples from all possible finite flonums (which is not the same
as uniform sample from a range of real numbers).
See finite-flonums$
in data.random
- Random data generators.
The general rational number generator created by rational-generator
evenly samples from an exact rational number generator and
an inexact rational number generator.
[SRFI-252]{srfi.252
}
Return generators that yields real numbers, exact real numbers,
and inexact real numbers, respectively.
In Gauche, the set of exact real numbers are exactly the same as
the set of exact rational numbers (infinites and NaNs are inexact),
so exact-real-generator
is the same as
exact-rational-generator
.
The inexact real number generator yields
0.0
, -0.0
, 0.5
, -0.5
,
1.0
, -1.0
, +inf.0
, -inf.0
, and +nan.0
at the beginning, followed by inexact real numbers uniformly sampled
from all possible finite flonums (which is not the same
as uniform sample from a range of real numbers).
See finite-flonums$
in data.random
- Random data generators.
The general real number generator created by real-generator
evenly samples from an exact real number generator and
an inexact real number generator.
[SRFI-252]{srfi.252
}
In Gauche, the set of exact numbers is the same as
the set of exact rational numbers (we don’t have exact complex),
and the set of inexact numbers
is the same as the set of inexact complex numbers.
Thus exact-number-generator
is the same as
exact-rational-generator
, and
inexact-number-generator
is the same as
inexact-complex-generator
.
The general number generator created by number-generator
evenly samples from an exact number generator and
an inexact number generator.
[SRFI-252]{srfi.252
}
Return generators that yield a list/vector of random length
up to max-length,
and elements generated by elt-generator, respectively.
Similar to lists-of
/vectors-of
in data.random
.
When max-length is omitted, we leave the length to the default
of lists-of
/vectors-of
,
which is determined by the parameter
default-sizer
in data.random
.
See data.random
- Random data generators, for the details.
[SRFI-252]{srfi.252
}
Returns a generator that yields pairs, whose car is generated
with car-generator
and whose cdr is generated
with cdr-generator
. If cdr-generator is omitted,
car-generator
is used.
[SRFI-252]{srfi.252
}
Returns a generator that yields procedures, which accepts
any number of arguments and returns a value generated with
value-generator.