(in-package :it.bese.FiveAM)
-;;;; * Random (QuickCheck-ish) testing
+;;;; ** Random (QuickCheck-ish) testing
;;;; FiveAM provides the ability to automatically generate a
;;;; collection of random input data for a specific test and run a
(defclass for-all-test-never-run (test-failure for-all-test-result)
())
-;;;; ** Generators.
+;;;; *** Generators
;;;; Since this is random testing we need some way of creating random
-;;;; data to feed to our code. Generators are regular functions whcih
+;;;; data to feed to our code. Generators are regular functions which
;;;; create this random data.
;;;; We provide a set of built-in generators.
(lambda () ,@body)))
(defgenerator gen-integer (&key (max (1+ most-positive-fixnum))
- (min (1+ most-negative-fixnum)))
+ (min (1- most-negative-fixnum)))
(+ min (random (1+ (- max min)))))
-(defgenerator gen-character (&key (code (gen-integer :min 0 :max (1- char-code-limit))))
- (code-char (funcall code)))
-
-(defun gen-string (&key
- (length (gen-integer :min 0 :max 80))
- (elements (gen-character))
- (element-type 'character))
- (lambda ()
- (loop
- with length = (funcall length)
- with string = (make-string length :element-type element-type)
- for index below length
- do (setf (aref string index) (funcall elements))
- finally (return string))))
-
-(defun gen-list (&key
- (length (gen-integer :min 0 :max 10))
- (elements (gen-integer :min -10 :max 10)))
- (lambda ()
- (loop
- repeat (funcall length)
- collect (funcall elements))))
+(defgenerator gen-character (&key (code (gen-integer :min 0 :max (1- char-code-limit)))
+ (alphanumericp nil))
+ (if alphanumericp
+ (code-char (funcall code))
+ (loop
+ for char = (code-char (funcall code))
+ until (alphanumericp char)
+ finally (return char))))
+
+(defgenerator gen-string (&key (length (gen-integer :min 0 :max 80))
+ (elements (gen-character))
+ (element-type 'character))
+ (loop
+ with length = (funcall length)
+ with string = (make-string length :element-type element-type)
+ for index below length
+ do (setf (aref string index) (funcall elements))
+ finally (return string)))
+
+(defgenerator gen-list (&key (length (gen-integer :min 0 :max 10))
+ (elements (gen-integer :min -10 :max 10)))
+ (loop
+ repeat (funcall length)
+ collect (funcall elements)))
;;;; The trivial always-produce-the-same-thing generator is done using
;;;; cl:constantly.