This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-11-03
Channels
- # announcements (17)
- # asami (17)
- # babashka (20)
- # beginners (110)
- # calva (1)
- # cherry (3)
- # cider (1)
- # clj-kondo (21)
- # clj-on-windows (1)
- # cljsrn (5)
- # clojure (142)
- # clojure-austin (1)
- # clojure-europe (72)
- # clojure-france (28)
- # clojure-hungary (2)
- # clojure-nl (2)
- # clojure-norway (38)
- # clojure-poland (2)
- # clojure-uk (3)
- # clojurescript (4)
- # cursive (33)
- # data-science (3)
- # datahike (5)
- # datomic (1)
- # emacs (27)
- # events (3)
- # fulcro (15)
- # graalvm (4)
- # gratitude (2)
- # honeysql (7)
- # humbleui (8)
- # introduce-yourself (11)
- # jobs-discuss (9)
- # lambdaisland (3)
- # lsp (18)
- # malli (62)
- # music (1)
- # nbb (3)
- # off-topic (10)
- # pathom (3)
- # pedestal (6)
- # polylith (5)
- # re-frame (7)
- # releases (2)
- # shadow-cljs (33)
- # sql (1)
- # test-check (23)
- # vim (20)
- # xtdb (9)
Is there a way do this, but in a way that has shrinkage? I want to pull a random character from a random string and then do stuff. The random string is made from a generator. Is there a way to move the random character into the prop/for-all?
(defspec split-functionality-test
(prop/for-all [s (gen/not-empty gen/string-alphanumeric)]
(let [split-on (rand-nth s) ;can this be done in the for-all binding?
pattern (re-pattern (str split-on))]
(= (cp-str/split s pattern) (str/split s pattern)))))
I would try something like
(defspec split-functionality-test
(prop/for-all [i gen/nat
s (gen/not-empty gen/string-alphanumeric)]
(let [split-on (nth s (mod i (count s)))
pattern (re-pattern (str split-on))]
(= (cp-str/split s pattern) (str/split s pattern)))))
sometimes it's helpful to build up the things you need rather than draw from one random thing
yeah, that's a decent way
potentially moving the order of i and s if it isn't shrinking well (I forget which way test.check throws away shrinking when composing with bind)
The other problem with my way is that because split-on is inside let
, I don't know the value of split-on when the test fails. So even if the shrinkage is worse, moving split-on to the prop/for-all could be a good tradeoff
in theory the ideal would be something like
(defspec split-functionality-test
(prop/for-all [s (gen/not-empty gen/string-alphanumeric)
i (gen/choose 0 (count s))]
(let [split-on (nth s (mod i (count s)))
pattern (re-pattern (str split-on))]
(= (cp-str/split s pattern) (str/split s pattern)))))
so you only generate numbers from 0 to size of string, and those generated numbers also predictably shrink (throwing the mod in there can make things weird when shrinking)
and when you compose things with bind like that in test.check(and anything modeled after the original quickcheck) you lose shrinking information for one or the other, and I forget which choice test.check makes
When I ran your second version it complained about i (gen/choose 0 (count s))]
. Said "Unable to resolve symbol: s in this context"
oh, good, I guess test.check's for-all is optimized to get around the issue I mentioned, but as a result the generators cannot refer to each other
I was looking at an old version of the code from before > When there are multiple binding pairs, the earlier pairs are not > visible to the later pairs. was added to the docstring for for-all
http://clojure.test.check.ge/let is what I am thinking of that allows for the dependencies between generators
Are there pitfalls/gotchas with using gen/let?
the above mentioned lose of shrinkage, which is https://clojure.atlassian.net/browse/TCHECK-112