reiddraper / simple-check

QuickCheck for Clojure
http://reiddraper.github.io/simple-check/
286 stars 18 forks source link

generators/one-of does not seem to shrink across provided generators. #28

Closed cstorey closed 10 years ago

cstorey commented 10 years ago

I'm using simple-check to test some parser-combinators, using simple-check to generate some random parsers, and I'm using one-of to choose between a series of parsers, like so:

(def re-gen
  (gen/one-of
    [(gen/return (re/zero))
     (gen/return (re/epsilon))
     (gen/fmap re/literal alphabet)]))

So Ideally, if a check for a certain parser fails, I'd like it to re-try the same check with a "simpler" parser, so the shrinking order would be something like (re/literal :z) → (re/literal :a) → (re/epsilon) → (re/zero).

However, that doesn't seem to be the case. Looking at the rose-tree representations, one-of seems to choose a sub-generator and then delegate the shrinking entirely to that generator. So, for example:

user=> (pprint (take 10 (repeatedly #(gen/call-gen (gen/one-of [(gen/elements [:foo :bar]) gen/boolean ]) (java.util.Random.) 7))))
([true ([false ()])]
 [:foo ()]
 [true ([false ()])]
 [:foo ()]
 [false ()]
 [:foo ()]
 [:bar ([:foo ()])]
 [true ([false ()])]
 [true ([false ()])]
 [:foo ()])
nil
user=>

I'd hoped to see a shrinking order of something like: :bar → :foo → true → false here. Would that make sense, do you think?

reiddraper commented 10 years ago

Nice observation. This is something I thought about a bit, and (somewhat arbitrarily) chose not to do. But I think I'm changing my mind. Fortunately, I think the change is pretty simple, and you can play around with this function to get you going:

(defn one-of-shrink
  [coll]
  (gen/bind (gen/choose 0 (dec (count coll)))
                (partial nth coll)))

Let me know if this works out, and I'll probably replace the current one-of implementation with this.

cstorey commented 10 years ago

Thanks! That seems to do exactly what I want. I did make a vague attempt to figure out how to do it myself, but I sadly couldn't quite see the wood for the trees, as it were.

Also, I just wanted to say a more general thanks for your hard work on the project, the shrinking functionality is very much appreciated.

reiddraper commented 10 years ago

You're quite welcome, happy to hear you're finding it useful.

reiddraper commented 10 years ago

ps., this is now included in 0.5.1