Hi Bill, Agreed, at least in part. I think that a good test suite for a language like Clojure should include both fixed values and generated ones. I just wanted both APIs to be available at the beginning so that volunteers could pick the most appropriate choice for a particular test.
Stuart > I applaud everyone who has volunteered to help write tests for > Clojure. A good test suite not only catches problems but also helps > beginners learn the language. > > Regarding the proposal in the previous post, I think we should be > careful about drawing inferences between the use of random values and > the resulting quality of the tests. In my experience, test developers > often use random values when fixed, hard-coded values work just as > well. I think it is more important to look for (and test) edge > conditions than it is to pull values out of a bag. I also think using > random values makes tests less reproducible. > > That's not to say there is never a time for randomization. I just > think it can make tests unnecessarily complicated. > > Bill > > On Oct 26, 12:47 pm, Meikel Brandmeyer <[EMAIL PROTECTED]> wrote: >> Dear Clojurians, >> >> Stuart brought up the idea of implementing a QuickCheck clone >> for Clojure. I think that this is a good idea, since it provides >> a much better coverage of possible inputs. I gave it some thought >> this weekend and the following is, what I came up with. There >> are some specifics of the API which I will ignore in the beginning. >> They will be explained later on. >> >> Comments, thoughts, improvements appreciated. >> >> ClojureCheck generates random input samples and feeds them to >> the functions under test. The generation is done via generation >> functions, which are combined via so-called combinators to more >> complex generators. >> >> The core is the function arbitrary. It generates the random values >> for a given type. As Stuart already suggested, I think a multi >> method is the best way to model this. >> >> (defmulti arbitrary (fn [x & _] (if (vector? x) (first x) x))) >> >> The first value is itself normally unused, since it normally >> only gives the type on which we dispatch. So we can for example >> define a generator for integers. >> >> (defmethod arbitrary Integer >> [_ size] >> (int (Math/round (* size (.nextDouble *prng*))))) >> >> (arbitrary Integer 100) >> >> To use a generator one uses for-all. >> >> (for-all [x Integer >> y Integer] >> (test-is/is (= (+ x y) (+ y x)))) >> >> This code actually cannot be used directly. You may have noticed >> the unexplained size parameter in the arbitrary call. This is a >> special parameters passed to the generators to allow a scaling >> of the test samples. So a generator of lists may start with short >> lists and may generate longer and longer lists as the test iterates. >> To hide this from the developer for-all actually returns a generator >> itself, ie. a function which accepts the size parameter and passes >> it on the generators in the binding form. So to run actually the >> tests, one uses the property function. >> >> (property >> (for-all [x Integer >> y Integer] >> (test-is/is (= (+ x y) (+ y x))))) >> >> This runs the tests for certain (configurable) number of iterations. >> Binding x and y to random integers each time. >> >> But sometimes one wants to pass parameters to the generators. I >> thought about the way eg. require does this: (require [foo :as bar]). >> So I thought one could do this by specifying a vector in the binding >> form. >> >> (for-all [x [:IntegerRange 100 1000]] >> (test-something-with x)) >> >> (defmethod arbitrary :IntegerRange >> [[_ mn mx] _] >> (int (Math/round (+ mn (* (- mx mn) (.nextDouble *prng*)))))) >> >> The environment like the random number generator, the number of >> test iterations etc. would be configurable at runtime. >> >> A first prototype looks promising. But before I run to far in the >> wrong direction, I'd like to ask for comments on the API so far. >> Especially things like passing arguments via a vector... >> >> Sincerely >> Meikel >> >> smime.p7s >> 5KViewDownload > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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 -~----------~----~----~----~------~----~------~--~---