Cedric Martin
Cedric Martin

Reputation: 6014

How to generate random elements depending on previous elements using Quickcheck?

I'm using QuickCheck to do generative testing in Clojure.

However I don't know it well and often I end up doing convoluted things. One thing that I need to do quite often is something like that:

However I have no idea as to how to do that cleanly using QuickCheck.

Here's an even simpler, silly, example which doesn't work:

(prop/for-all [a (gen/choose 1 10)
               b (gen/such-that #(= a %) (gen/choose 1 10))]
                (= a b))

It doesn't work because a cannot be resolved (prop/for-all isn't like a let statement).

So how can I generate the three primes, with the condition that the two latter ones are inferior to the first one?

Upvotes: 1

Views: 107

Answers (1)

mange
mange

Reputation: 3212

In test.check we can use gen/bind as the bind operator in the generator monad, so we can use this to make generators which depend on other generators.

For example, to generate pairs [a b] where we must have (>= a b) we can use this generator:

(def pair-gen (gen/bind (gen/choose 1 10)
                        (fn [a]
                          (gen/bind (gen/choose 1 a)
                                    (fn [b]
                                      (gen/return [a b]))))))

To satisfy ourselves:

(c/quick-check 10000
               (prop/for-all [[a b] pair-gen]
                 (>= a b)))

gen/bind takes a generator g and a function f. It generates a value from g, let's call it x. gen/bind then returns the value of (f x), which must be a new generator. gen/return is a generator which only generates its argument (so above I used it to return the pairs).

Upvotes: 3

Related Questions