doc.txt

fasttest.plt : FastTest Random Test Case Generation

_fasttest.plt : FastTest Random Test Case Generation_

Written by: Carl Eastlund (cce at ccs dot neu dot edu)
       and: Carter Schonwald (carter dot schonwald at yale dot edu)
Keywords: _quickcheck_ _randomized_ _testing_

================================================================================

FastTest is a library for random generation of test cases for unit testing.  It
was inspired by the QuickCheck library for Haskell [1].  It includes two
libraries:

random.ss : Randomized generators for sets of data.
schemeunit.ss : SchemeUnit integration for testing based on generators.

[1] http://www.cs.chalmers.se/~rjmh/QuickCheck/

================================================================================

_random.ss : Random data generation_

This module provides support for randomized generation of values based on
user-defined distributions.  It provides one new type, described immediately
below, and the values and macros which follow:

A (Generator T) is a source of random values of type T.

--------------------

> (generator? v) : Boolean
  v : Any

Reports whether v is a generator.

--------------------

> (generate gen) : T
  gen : (Generator T)

Constructs a random value from the given generator.

--------------------

> (nonrandom v) : (Generator v)
  v : Any

Generates the given value deterministically.

Example: (generate (nonrandom 'value)) ;; 'value

--------------------

> (random-int-between i j) : (Generator Nat)
  i : Integer
  j : Integer

Generates a random integer chosen uniformly between i and j, inclusive.

Example: (generate (random-int-between 1 10)) ;; 7, 3, 10, 9, 1, 8

--------------------

> (random-size [min]) : (Generator Nat)
  min [= 0] : Nat

Generates potentially unbounded, but usually small, natural numbers, often
useful for determining the size of other random data.

Produces min+k for some natural number k; the chance of k being 0 is 1/4, of 1
is 1/4, and for any larger integer i is 1/2^i.

Example: (generate (random-size)) ;; 1, 3, 2, 0, 4, 2, 0, 1

--------------------

> random-boolean : (Generator Boolean)

Generates fairly-chosen booleans.

Example: (generate random-boolean) ;; #t, #f

--------------------

> (random-char [code-gen]) : (Generator Char)
  code-gen [= (random-int-between 32 127)] : (Generator Nat)

Generates characters whose code is chosen from code-gen.

Example: (generate (random-char)) ;; #\c, #\9, #\space, #\A

--------------------

> (random-uniform make elem-gen [len-gen]) : (Generator (Groupof T))
  make : T ... -> (Groupof T)
  elem-gen : (Generator T)
  len-gen [= (random-size)] : (Generator Nat)

Generates a random collection of elements.  It chooses a number of elements from
len-gen, generates each from elem-gen, and passes them to the constructor make.

Example: (random-uniform list* (random-symbol)) ;; 'x, '(A b7 . -g)

> (random-list-of elem-gen [len-gen]) : (Generator (Listof T))
> (random-vector-of elem-gen [len-gen]) : (Generator (Vectorof T))
> (random-string [char-gen len-gen]) : (Generator String)
> (random-bytes [byte-gen len-gen]) : (Generator Bytes)
  elem-gen : (Generator T)
  char-gen [= (random-char)] : (Generator Char)
  byte-gen [= (random-int-between 0 255)] : (Generator Byte)
  len-gen [= (random-size)] : (Generator Nat)

Generators for lists, vectors, strings, and byte strings, equivalent to
random-uniform with the added first argument of list, vector, string, or bytes,
respectively.

--------------------

> (random-apply f gen ...) : (Generator B)
  f : A ... -> B
  gen ... : (Generator A) ...

Generates the result of applying f to random inputs chosen from each gen.

Example: (generate (random-apply cons (random-char) (random-string)))
         ;; '(#\c . "+8Y")

> (random-list gen ...) : (Generator (list T ...))
> (random-vector gen ...) : (Generator (vector T ...))
  gen : (Generator T) ...

Generators for random heterogenous lists and vectors, equivalent to random-apply
with the added first argument of list or vector, respectively.

--------------------

> (random-symbol [name-gen]) : (Generator Symbol)
  name-gen [= (random-string)] : (Generator String)

Generates random interned symbols whose names are chosen from name-gen.
Equivalent to (random-apply string->symbol name-gen).

Example: (generate (random-symbol)) ;; 'x, '|0A-|, 'fY, '@

--------------------

> (random-choice gen1 ... genK) : (Generator (Union T1 ... TK))
  gen1 ... genK : (Generator T1) ... (Generator TK)

Generates a value from a fairly chosen generator out of gen1 ... genK.

Example: (generate (random-choice (nonrandom 'A) (nonrandom 'B))) ;; 'A, 'B

--------------------

> (random-weighted prob1 gen1 ... probK genK) : (Generator (Union T1 ... TK))
  prob1 ... probK : Positive-Rational
  gen1 ... genK : (Generator T1) ... (Generator TK)

Generates a value from a generator chosen with the associated weight.

Example: (generate (random-weighted 1 (nonrandom 'A)
                                    3 (nonrandom 'B))) ;; 'B, 'A, 'B, 'B

--------------------

> (random-recursive rec-gen [prob1 gen1] ... [probK genK]) : (Generator T)
  prob1 ... probK : Positive-Rational
  gen1 ... genK : (Generator T)

This macro creates a generator for a recursive data structure whose clauses are
generated by gen1 ... genK with respective probabilities prob1 ... probK; the
recursive generator is in scope for gen1 ... genK under the name rec-gen.

Example:

(define-struct leaf (data))
(define-struct node (left right))

(random-recursive tree-gen
  [1 (nonrandom (make-leaf))]
  [4 (random-apply make-node tree-gen tree-gen)])

--------------------

> (random-function f) : (Generator (A ... -> B))
  f : A ... -> (Generator B)

Generates a function that produces random outputs.  For each set of inputs, the
resulting function will get the corresponding generator from f and produce a
value from it.  The function will memoize these values to produce consistent
results for any specific set of inputs.

Examples:

(define f
  (generate
   (random-function
    (lambda (n)
      (random-list (random-boolean) (nonrandom n))))))

      ;; Notice how (f 5) always produces the same list of 5 booleans:
(f 5) ;; '(#f #f #t #f #t)
(f 2) ;; '(#t #t)
(f 5) ;; '(#f #f #t #f #t)
(f 3) ;; '(#t #f #t)
(f 5) ;; '(#f #f #t #f #t)

================================================================================

_schemeunit.ss : Randomized SchemeUnit testing_

--------------------

> (test-randomly name count ((var gen) ...) body ...) : Test-Suite
  name :: (Literal String)
  count :: (Literal Nat)
  var :: Identifier
  gen :: Expression
  body :: Expression

Generates a test suite containing count tests, each of which is annotated with
the index of the test and the randomly chosen values, but is otherwise
equivalent to:

(test-case name
  (let* ((var (generate gen)) ...)
    body ...))

Example:

(test-randomly "list-ref produces a member" 100
  ([the-list (random-list-of (random-symbol))]
   [the-index (random-int-between 0 (- (length the-list) 1))])
  (check-not-false
   (member (list-ref the-list the-index) the-list)))