Scheme-Check is a module that implements randomized unit testing in PLT Scheme. With Scheme-Check, instead of creating lots of individual tests, you specify properties of your code and Scheme-Check generates a large amount of random data sets to test those properties. Scheme-Check is basically a Scheme port of QuickCheck.
Download Scheme-Check | |
The latest version of Scheme-Check is 0.21 | |
Usage | |
This is a very simple example of defining and using properties with Scheme-Check. > (define reverse-list
... definition ...)
> (define append-list
... definition ...)
> (define (property-reverse l1 l2)
(equal? (append-list (reverse-list l1) (reverse-list l2))
(reverse-list (append-list l2 l1))))
> (test-property property-reverse '((list-of integer) (list-of integer)))
Ok, passed 100 tests.
(ok 1.0)
>
You can also define new types and how to generate values. For example, Scheme-Check provides ways to test structures: > (define-struct point (x y))
> (define-testable-struct point ((x integer) (y integer)))
> (define (distance p1 p2)
.. returns euclidean distance between points
> (define (distance-obeys-triangle-inequality p1 p2 p3)
(let ([p1p2 (distance p1 p2)]
[p2p3 (distance p2 p3)]
[p1p3 (distance p1 p3)])
(>= (+ p1p2 p2p3) p1p3)))
> (test-property distance-obeys-triangle-inequality '(point point point))
Ok, passed 100 tests.
(ok 1.0)
The value returned, (ok 1.0) is intended to allow automatic evaluation of the tests performed. Scheme-Check allows much more flexibility over the generation of the test data. For example, there are ways to specify the quality of the generated test data, to create conditional properties (that is, properties that are only tested if the test data satisfies some constraints), to create random functions, and more. There is no official documentation yet but the module includes a file with some examples, and even uses itself for some tests, so looking at the source will teach you quite a bit. Also, reading the original QuickCheck paper very probably will help. | |
Caveats | |
The original QuickCheck module did not have to worry about the global state of the program, because Haskell is a purely functional language. Scheme, on the other hand, allows mutation, and so there must be a way to test impure functions. There is no explicit way yet to do this using Scheme-Check. It would be impractical (if not impossible) to know whether a function is pure or not and on which global variables it depends without analyzing the source code of the programs to be tested. This is not the goal of Scheme-Check, and so some other way must be found. I'm still on the lookout here, so any suggestions are welcome. Currently, a workaround is to define the properties with additional parameters and set! the global variables in which the code depends on before actually testing the properties. | |
Last modified: 23 August 2003 | |