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.