reiddraper / simple-check

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

Add nested property support #10

Closed reiddraper closed 10 years ago

reiddraper commented 11 years ago

Something like:

(defn exists?
  [e coll]
  (some #{e} coll))

(defn remove-elem
  [e coll]
  (remove #{e} coll))

;; this test should fail, and illustrates nested properties
(quick-check (for-all [v (gen/vector gen/int)]
               (for-all [e (elements v)]
                 #(exists? e (remove-elem e v)))))

This will require support for reifying properties, which we don't currently.

si14 commented 11 years ago

Hi, is there any plans on this? We are currently trying to adopt simple-check in core.matrix and being unable to make one generator depend on another makes property testing much less powerful then it can be.

reiddraper commented 11 years ago

Yes. I hope to get to this soon. The good news, however, is that you can write generators that depend on each other now. For example, I rewrote your proper-vector-test to also generate the high and low bounds for the vector. Here's the generator. The key is to use the bind function. Here's another simple example:

(require '[simple-check.core :as sc])
(require '[simple-check.generators :as gen])
(require '[simple-check.properties :as prop])

(def non-empty-vector
  (gen/such-that not-empty (gen/vector gen/int)))

(def vector-and-random-element
  (gen/bind non-empty-vector
                (fn [v] (gen/tuple [(gen/return v) (gen/elements v)]))))

(gen/sample vector-and-random-element)
;; ([[1] 1] [[0 -1] -1] [[1] 1] [[0 3 1] 0] [[-4 -4] -4] [[0] 0] [[-4] -4] [[-6 -1 2 -5 2 1 2] -1] [[-9 8 -8 0 1 -1 6 8] -8] [[-1 -1 5 1 1 -10 10] 1])
si14 commented 11 years ago

Thank you! I must have missed this in the documentation.

reiddraper commented 11 years ago

Thank you! I must have missed this in the documentation.

Don't think it was documented. Will work on getting bind documented soon.

reiddraper commented 10 years ago

Thinking a little bit out loud here, I think the solution is for for-all to note the return-value of the expression, and if another generator is returned (recall that properties are actually generators too), then call bind with that property. If not, continue as things are today. When calling bind, we'll need some way to 'combine' the values generated from the outer property and the inner property, so you can see at which 'level' your failing values were generated.

reiddraper commented 10 years ago

Moved to Jira.

maciejjaskowski commented 10 years ago

What's the status of this issue? It would help us a lot to have this functionality up and running in the following case: I want to verify my path finding algorithm finds optimal solution in the given graph G, so I generate the graph and a big number of random paths and check that all the random paths are "less optimal" then the one found by the algorithm.

Having nested for-all that would be simple. Is there a way around?

reiddraper commented 10 years ago

responding on Jira, but yes, there is a 100% way around it. Nested properties are just a convenience.