Hello I’m trying to use test.check to generate a string that is formatted as MM/dd/yyyy.
I have the following function
(defn- gen-date [start end]
(tgen/let [months (tgen/choose 1 12)
days (tgen/choose 1 31)
years (tgen/choose start end)
padding (fn [num-to-pad]
(if (< 1 num-to-pad 9)
(clojure.string/join "" [0 num-to-pad])
(str num-to-pad)))
month-str (tgen/fmap #(padding %) months)
day-str (tgen/fmap #(padding %) days)
year-str (tgen/fmap str years)]
(let [m (tgen/one-of [month-str])
d (tgen/one-of [day-str])
y (tgen/one-of [year-str])]
(tgen/fmap clojure.string/join "/" [m d y]))))
I can’t seem to wrap my head around the last step which is to merge all the generators into a generator that will produce the final string.
tgen is an alias for test.check.generators. Any insight will be greatly appreciated.
If your intent is to generate dates, note that any of these approaches can return non-existing dates- e.g. Feb 31.
This function will return one string:
(defn- gen-date [start end]
(let [months (tgen/choose 1 12)
days (tgen/choose 1 31)
years (tgen/choose start end)
padding (fn [num-to-pad]
(if (<= 1 num-to-pad 9)
(clojure.string/join "" [0 num-to-pad])
(str num-to-pad)))
month-str (tgen/fmap padding months)
day-str (tgen/fmap padding days)
year-str (tgen/fmap str years)]
(->> [month-str day-str year-str]
(mapv tgen/generate)
(clojure.string/join "/"))))
(gen-date 2005 2014)
=> "01/28/2006"
(gen-date 2005 2014)
=> "05/12/2005"
(gen-date 2005 2014)
=> "10/14/2013"
And this one returns generator:
(defn- gen-date2 [start end]
(let [months (tgen/choose 1 12)
days (tgen/choose 1 31)
years (tgen/choose start end)
padding (fn [num-to-pad]
(if (<= 1 num-to-pad 9)
(clojure.string/join "" [0 num-to-pad])
(str num-to-pad)))
month-str (tgen/fmap padding months)
day-str (tgen/fmap padding days)
year-str (tgen/fmap str years)]
(tgen/fmap (fn [[m d y]] (clojure.string/join "/" [m d y]))
(tgen/tuple month-str day-str year-str))))
(tgen/sample (gen-date2 2010 2020) 10)
=>
("07/15/2020"
"04/02/2016"
"03/10/2011"
"05/03/2011"
"03/02/2019"
"08/23/2015"
"06/16/2015"
"09/04/2017"
"06/26/2019"
"03/18/2019")
Shortened:
(defn- gen-date [start end]
(->> [(tgen/choose 1 12) (tgen/choose 1 31) (tgen/choose start end)]
(mapv tgen/generate)
(apply format "%02d/%02d/%04d")))
(defn- gen-date2 [start end]
(tgen/fmap (fn [[m d y]] (format "%02d/%02d/%04d" m d y))
(tgen/tuple (tgen/choose 1 12)
(tgen/choose 1 31)
(tgen/choose start end))))
Thank you. I wish I had thought of format.