Since there is now a movement afoot to write a comprehensive test
suite, I want to re-post the spike I did earlier on ClojureCheck.
It would be cool to use check-style tests for at least part of the
Clojure suite. If there is interest in this, I hope to have time to
work on this in late November, or would be delighted if someone else
picks up the idea and runs with it.
Original message follows:
---------------
At the JVM summit Clojure breakout someone suggested a Haskell
QuickCheck/ScalaCheck library for Clojure. I am attaching a small
spike in that direction below. A few questions:
(1) Is anybody interested?
(2) If the answer to (1) is yes, do you like the direction I am going
in the public API, e.g.
(for-all [x Integer y Integer] (some stuff that must be true))
(3) Any suggestions about implementation detail? (E.g. I like using a
multimethod for arbitrary--is there a prettier syntax for ignoring the
argument after using it for dispatch?)
Cheers,
Stuart
;;; clojure_check.clj: quick check framework for Clojure
;; Copyright (c) 2008 Stuart Halloway. All rights reserved.
;; Inspired by Scalacheck et al (http://code.google.com/p/scalacheck/)
;; Licensed under the same CPL as Clojure (http://clojure.org)
;; Uses clojure.contrib.test-is for assertions
;;
;; Example (passing)
;; (for-all [x Integer y Integer] (= (+ x y) (+ y x)))
;;
;; Example (failing)
;; (for-all [x Integer y Integer] (= (+ x y) (- y x)))
(ns clojure-check
(:import (java.util Random))
(:use clojure.contrib.test-is))
(defmulti arbitrary identity)
(def random (Random.))
(defn collection-size []
(.nextInt random 100))
(def *check-count* 50)
(defn choose [rng]
(nth rng (.nextInt random (count rng))))
(defmethod arbitrary Integer [_] (.nextInt random))
(defmethod arbitrary Character [_] (char (.nextInt random)))
(defmethod arbitrary :ascii-character [_] (char (choose (range 32
128))))
(defmethod arbitrary String [_]
(apply str (take (collection-size) (iterate (fn[_] (arbitrary
Character)) nil))))
(defmethod arbitrary :ascii-string [_]
(apply str (take (collection-size) (iterate (fn[_] (arbitrary :ascii-
character)) nil))))
(defmacro binding-values [& vars]
`(vector ~@(map (fn [v] `['~v ~v]) vars)))
(defmacro for-all [args & forms]
(let [vars (take-nth 2 args)
value-generators (map (fn [x] `(arbitrary ~x))(take-nth 2 (rest
args)))]
`(do
~@(map (fn [f]
`(dotimes i# *check-count*
(let ~(apply vector (interleave vars value-generators))
(is (true? ~f) (pr-str (binding-values [EMAIL
PROTECTED]))))))
forms))))
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---