Fork me on GitHub
#test-check
<
2016-07-27
>
metametadata02:07:23

@ag @gfredericks your snippets both seem to work and produce similar results

metametadata02:07:11

refactoring @ag's version I came up with this (extracted amount and gen-when):

(defn gen-when
  [x gen]
  (gen/let
    [x (gen/return x)]
    (when x gen)))

(def gen-card
  (gen/let
    [debit? gen/boolean
     amount gen/pos-int]
    (gen/hash-map
      :created-at gen/pos-int
      :amount-debit (gen-when debit? amount)
      :amount-credit (gen-when (not debit?) amount))))
Sample:
({:created-at 0, :amount-debit 0, :amount-credit nil}
 {:created-at 0, :amount-debit nil, :amount-credit 0}
 {:created-at 0, :amount-debit nil, :amount-credit 2}
 {:created-at 2, :amount-debit 3, :amount-credit nil}
 {:created-at 4, :amount-debit nil, :amount-credit 0})
I tend to eliminate bind and fmap because for me they're harder to read than let. I also like here how using gen/hash-map allows to "inline" :created-at generator.

gfredericks02:07:16

@metametadata: your gen-when ignores its first argument

gfredericks02:07:35

oh I take it back

gfredericks02:07:37

okay so if you want to use let then I think (gen/let [debit? gen/boolean, amount gen/pos-int, created-at gen/pos-int] {:created-at created-at :amount-debit (when debit? amount) :amount-credit (when-not debit? amount)}) would be a bit more direct

gfredericks02:07:18

you don't get to inline the created-at generator but on the other hand you don't have to create wrapper generators for credit/debit

metametadata02:07:11

yeah, agree. I guess the approach will depend on the number of additional fields in the card map

metametadata02:07:25

ie if there are a lot of fields similar to created-at than "inlining" is more preferable

ag03:07:19

actually my thing worked, I didn't know it. My ui was broken, I couldn't see it :)

gfredericks03:07:39

@metametadata: you can also do both -- make two maps and merge them together

mattly21:07:46

has anyone written about reducing generation time for creating large tree structures in test.check ?

mattly21:07:34

I added a new branch in my structure recently and it tripled the test run time

mattly21:07:34

the branch is basically (gen/list-distinct-by :name (gen/hash-map :name gen/string-alphanumeric)) and gets fmapped over with some other stuff

mattly21:07:45

the actual value of the string isn't important so much as that it's distinct

mattly21:07:23

so I'm looking at strategies for getting rid of the distinct clause in the list generator and making the value distinct some other way

mattly21:07:34

I'd also love to know if there's a way to peek a bit better at which parts of my tree are taking the most time generate

gfredericks22:07:18

mattly: have you checked if the runtime increase roughly corresponds to an increase in the size of the generated data?

mattly22:07:42

gfredericks: working on it

mattly22:07:49

but I think it does

gfredericks22:07:53

if it does correspond, then my initial reaction would be "that sounds reasonable"; if not, then that could potentially be a problem worth looking into

gfredericks22:07:10

unless I'm misunderstanding your question

mattly22:07:40

I don't think it's a problem of test.check per-se so much as the data structure I'm creating with it

gfredericks22:07:05

mattly: how familiar are you with test.check's general sizing mechanism?

mattly22:07:40

gfredericks: I've dug into the code a bit but haven't tried writing my own generator beyond composing from primitives

gfredericks22:07:55

you shouldn't need to normally

gfredericks22:07:45

I suppose I'm just wondering if you understand it well enough to know why (gen/vector (gen/vector (gen/vector (gen/vector (gen/vector gen/nat))))) would OOM

mattly22:07:54

I'm pretty sure the problem stems from the need for distinct values where the value doesn't actually matter at a low point in the tree, and then having to generate all the child branches

mattly22:07:10

I've run into that quite a bit on Circle 😄

mattly22:07:34

most of my lists / vectors anymore I put max-elements on

gfredericks22:07:23

I think the distinct generator is highly unlikely to be slow without also throwing exceptions

gfredericks22:07:56

i.e., if you think the problem is that it has to throw away a bunch of stuff because of collisions

mattly22:07:08

that was my guess

gfredericks22:07:18

it'll throw an exception if it can't generate a unique thing after ~10 tries

gfredericks22:07:28

so it's hard to imagine a scenario where it expends much effort on this without hitting 10 occasionally

mattly22:07:36

fair point

mattly23:07:58

I got some instrumentation up around the generators and my test runs

mattly23:07:17

eliminating the need to generate distinct values on one branch of my tree cut the test run time in half

mattly23:07:42

I'm basically putting those values in now after-the-fact similar to how you might do serial ids