This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-05-22
Channels
- # announcements (1)
- # beginners (109)
- # boot (2)
- # calva (26)
- # cider (6)
- # circleci (6)
- # cljsrn (3)
- # clojure (77)
- # clojure-dev (5)
- # clojure-europe (28)
- # clojure-finland (1)
- # clojure-hamburg (1)
- # clojure-italy (21)
- # clojure-japan (13)
- # clojure-nl (36)
- # clojure-spec (22)
- # clojure-sweden (4)
- # clojure-uk (105)
- # clojurescript (91)
- # community-development (8)
- # cursive (60)
- # datascript (3)
- # datomic (4)
- # emacs (33)
- # fulcro (19)
- # graalvm (38)
- # hoplon (4)
- # instaparse (1)
- # jobs (1)
- # leiningen (22)
- # off-topic (14)
- # pathom (2)
- # perun (4)
- # planck (5)
- # re-frame (10)
- # reagent (1)
- # reitit (11)
- # rum (11)
- # shadow-cljs (97)
- # tools-deps (82)
- # vim (53)
@alexmiller To improve docs of the lazy-loaded gen/* functions, since including the whole docstring is not feasible according to https://clojure.atlassian.net/browse/CLJ-2018, what about at least changing the docstring to contain the URL of the function's online documentation, such as http://clojure.github.io/test.check/clojure.test.check.generators.html#var-elements for elements
?
Should I make a jira issue and send a patch?
Go for it
@alexmiller I wanted to try my patch by including local clone of spec.alpha in my project but starting clj
in my project then fails with
...
Caused by: java.lang.Exception: #object[clojure.spec.alpha$and_spec_impl$reify__1047 0xf9b5552 "clojure.spec.alpha$and_spec_impl$reify__1047@f9b5552"] is not a fn, expected predicate fn
at clojure.spec.alpha$dt.invokeStatic(alpha.clj:762)
...
Any idea what I do wrong?
I have cloned to /Users/me/tmp/spec.alpha
, git hash 5228bb7. In my project's deps.edn
: {:deps {org.clojure/clojure {:mvn/version "1.10.1-beta2"}
org.clojure/spec.alpha {:local/root "/Users/me/tmp/spec.alpha"}
...}
(This is before I did any changes to the code. java -version
1.8.0_192, OSX)
But mvn package
in the spec.alpha
project runs just fine.Same problem when running clj in the spec.alpha project:
🐟 clj
Clojure 1.10.0
user=> (load-file "src/main/clojure/clojure/spec/alpha.clj")
Syntax error macroexpanding clojure.core/defn at (alpha.clj:78:1).
#object[clojure.spec.alpha$and_spec_impl$reify__2183 0x1698fc68 "clojure.spec.alpha$and_spec_impl$reify__2183@1698fc68"] is not a fn, expected predicate fn
(Added https://clojure.atlassian.net/browse/CLJ-2512 for the docstring change)
Question: I often do something like the following, to restrict the domain of the generated values to ensure interesting conflicts:
(s/fdef filter-adult-users
:args (s/cat :youngsters (s/coll-of ::uid :kind set?), :users ::users) #_... )
(deftest filter-adult-users-spec
(let [[user-ids] (sg/sample (sg/set (s/gen ::uid)
{:min-elements 1
:max-elements 20})
1)]
(is (true? (check `filter-adult-users
{:gen {::uid (constantly (sg/elements user-ids))}})))))
I.e. I have a let
where I use sample
to generate a random, small set of data then used in generator overrides in the test itself. Do you do that too? Is there a better way?
update Sometimes I need to use the customized random data from multiple generators, which prevents I. believe the usage of simple generator derivation such as gen/let and gen/rmaphave a look at test.check/fmap
, test.check/bind
and test.check/let
:
https://github.com/clojure/test.check/blob/master/doc/cheatsheet.md#combinators
https://github.com/clojure/test.check/blob/master/doc/intro.md#bind
@holyjak
https://github.com/clojure/test.check/blob/master/src/main/clojure/clojure/test/check/generators.cljc#L1570
thank you! but what if eg 2 different generators need the value? any tips?
yep, that’s a very interesting need …
example: having a function taking a map with known values and a list of "things", the fn throws if any " thing" has an unknown value. If I want to test its other functionality I must ensure that things only use the values in the map get I prefer not to hardcode the map.
you can test.check/let
the generator, which generates [map things] tuples, and then apply function you want to test to the generated tuples
good idea! But I guess I would need to invoke it manually instead of using spec.test/check
defining wrapper which applies your function to the tuple, and specing/checking wrapper instead might be an option for you
could anyone write/share a gist detailed example 🙏 ? 🙂
BTW I tried to replace my (let [uids ..] (check .. {:gen {::uid (const. (sg/elements uids)))}}))
with
(check ..
{:gen {::uid (constantly
(gen/bind
(sg/set (s/gen ::kd/sid) :num-elements 1)
sg/elements))}})
but it does not seem to really work. If I replace it with (constantly (sg/return (s/gen ::uid)))
then I get many (desired) "collisions" in the tests but with ☝️ I get none. So my hypothesis is that the set of values is re-created every time that a new value fpr ::uid is generated, instead of creating it once and reusing it every time ::uid is requested.@U051KJGTX a gist of what exactly? As mentioned above, bind did not work for me, and showing a let wrapping check with some :gen overrides is perhaps not all that interesting?
@U051KJGTX here is an example of what misha proposed, a wrapper fn taking a tuple of related inputs:
(defn apply-profile-compute-totals-wrapper
"Smart wrapper around apply-profile-compute-totals that 'unpacks' the subscr-summaries+userid->profile tuple
we generate so that both have the same subscribers before invoking the wrapped fn
"
[subscr-summaries+userid->profile]
(let [[subscr-summaries userid->profile] subscr-summaries+userid->profile]
(apply-profile-compute-totals
{:db/userid->profile userid->profile}
subscr-summaries)))
(s/def ::subscr-summaries+userid->profile
(s/with-gen
(s/cat :subscr-summaries ::kd/subscr-summaries, :userid->profile :db/userid->profile)
;; GENERATOR: Ensure that the generated userid->profile have a profile for every subscriber in
;; subscr-summaries (b/c those without profile would have been filtered out before)
(constantly
(gen/let
[subscr-summaries (s/gen ::kd/subscr-summaries)
profiles (sg/vector (s/gen :db/profile) (count subscr-summaries))]
[subscr-summaries
(zipmap
(keys subscr-summaries)
profiles)]))))
(s/fdef apply-profile-compute-totals-wrapper
:args (s/cat :1 ::subscr-summaries+userid->profile)
;:args (s/cat
; :org (s/keys :req [:db/userid->profile])
; :subscr-summaries ::kd/subscr-summaries)
:ret ::kd/subscrs+profile-usages)
(st/check `apply-profile-compute-totals-wrapper)
thanks a lot for sharing … I’ll give a try next week!
here is more explanation about fmap and bind: https://youtu.be/F4VZPxLZUdA?t=655