thanks Alex and others for helping out. Some very interesting ideas here 
but the one about leveraging the grouping function seemed easy and reading 
that was an epiphany moment where i realised i had been subconsciously 
constrained by thinking I should generate data and use a grouping fn that 
was similar to the narrow ways I happen to have used the group-by fn in the 
past.

I would like to read more though and if I see good resources on scala or 
haskell equivalent I will try to pass on via pull request.

fyi, here are encodings of the 3 properties I originally stated. I used 
count for group-by fn in all 3.

;;test group by

(def vector-of-strings (gen/vector gen/string))

(def grouping-retains-all-input
  "flattening the vals of the group-by result should give back contents of 
the original collection"
  (prop/for-all [group-by-input vector-of-strings]
                (= (set group-by-input) (-> (group-by count group-by-input) 
vals flatten set))))

(def all-members-under-grouping-key-should-be-there
  "applying the grouping fn to each item under a grouping should result in 
the grouping key"
  (prop/for-all [group-by-input vector-of-strings]
                (every? #(= true %)
                       (map (fn [[key group]] (apply = key (map count 
group)))
                        (group-by count group-by-input)))))

(def grouping-does-not-duplicate
  (prop/for-all [group-by-input vector-of-strings]
                (= (count group-by-input) (-> (group-by count 
group-by-input) vals flatten count))))


On Thursday, May 1, 2014 12:49:31 AM UTC+1, Andrew Chambers wrote:
>
> One approach you can use is write the generators in such a way that they 
> generate the final answer group-by should return, then you write code
> which does the inverse to group by and then you check the group by answer 
> is equal to the originally generated solution.  
>
> On Wednesday, April 30, 2014 11:38:19 PM UTC+12, henry w wrote:
>>
>> Hi, I wanted to get started with clojure.test.check (formerly 
>> simple-check) and I am new to property based testing.
>>
>> I plucked clojure.core/group-by for no particular reason as a function to 
>> test.
>>
>> I started by stating some properties i think should hold:
>>
>> ;; 1. applying the grouping key function to each member in a grouping 
>> should result in the grouping key
>> ;; 2. flattening the vals of the group-by result should give back the 
>> contents of the original collection.
>> ;; 3. no element appears in more than one grouping.
>>
>> so far so good I think. there may be others but this seems ok for now. 
>>
>> now, how to generate some data.
>>
>> for group-by we need two params:
>> 1) a grouping function
>> 2) a collection of items to be grouped
>>
>> If I start by naively generating collections of maps (containing keyword 
>> keys and int vals, for example), the data is of the right shape to use in 
>> group by, but there is no guarantee that:
>> 1) any of the maps share a key that I could use for grouping
>> 2) the values under a common key are shared
>>
>> This is really the crux of my problem.... ideally I would have the 
>> generator *mostly* produce data which is actually doing to result in the 
>> sort of collection i might want to call group-by on in real life (ie not 
>> have everything grouped under nil on each generation). So should i create a 
>> generator that creates keywords (which i will want to use as grouping 
>> function) then have another generator that produces what are going to be 
>> the values under this grouping key, then a generator that uses both of 
>> these to create collections of maps from these. then i would have to find 
>> out what the grouping keyword was that was generated.... this could all 
>> work, I have read enough about generators to have a stab at this... but is 
>> it the right approach?
>>
>> as far as implementing tests for the properties so far, I have done 
>> property 2 above, using a basic generator and yanking out an arbitrary key 
>> from it.... clearly a flawed approach as not much 'realistic' grouping is 
>> going to happen here.
>>
>> (def vector-of-maps (gen/such-that not-empty (gen/vector (gen/such-that 
>> not-empty (gen/map gen/keyword gen/int)))))
>>
>> (def all-elements-are-grouped
>>   (prop/for-all [group-by-input vector-of-maps]
>>                 (let [a-map-key (-> group-by-input first keys first)] ;; 
>> hmm, seems far from ideal
>>                   (= (set group-by-input) (-> (group-by a-map-key 
>> group-by-input) vals flatten set)))))
>>
>> help appreciated... perhaps I need to learn more about the paradigm 
>> first, but resources linked from the readme are all a bit more basic than 
>> this. so if you know of some more advanced tutorials please let me know.
>>
>> Thanks
>>
>

-- 
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
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to