I've played around now with implementing specs for a couple of my projects.

What I'm finding is that writing specs to check the inputs of a function is
easy-ish, but building useful random generators is very hard -- in my
projects, this seems too hard to do with any reasonable amount of effort.

This isn't due to anything inherent in clojure.spec, it's just that for
non-trivial functions, coming up with relevant random input is a very hard
problem.  For example, let's say I have a function that takes two
integers.  Odds are that not any two randomly chosen integers will work.
Some combinations of integers are non-sensical and could trigger an error,
other combinations may cause the function to run way too long.  As a
concrete example, I just tried to spec out a SAT solver (which tries to
solve NP-complete problems).  The input should be a vector of vectors of
ints, but many combinations of inputs will just run forever.  How to
generate "good" SAT problems?  I have no idea.

So for the most part, I've ignored the generation aspect of specs because
it just feels like too much work.  But without the generators,
clojure.spec's utility is significantly diminished.

1. No way to test function output specs.  For documentation purposes, I
want to have an output spec on my function.  However, as far as I know,
after instrumentation-triggered checking of output specs was removed a
couple of alphas ago, the only way remaining to check against output specs
is to use randomly generated tests.  So if I can't make good generators, I
have no way to confirm that my output spec works the way I think it does.
My documentation could be totally out of touch with reality, and that
displeases me.

2. Limited ability for testing that functions take and receive what you
expect.  Whereas a static type system can prove certain properties about
whether functions are called with valid inputs, with spec, you only get
those guarantees if you pump a function with enough valid random data to
trigger the function calling all its callees with interesting combinations
of data.  But if I use the naive generators, the function will never even
complete with most of the randomly generated input, let alone call other
functions in a useful way.  And in many cases I don't see how to generate
something of better quality.

So looking back at my experiments, my preliminary impression is that by
adding specs to my public APIs, I've gained some useful documentation, and
I've given users the ability to instrument functions in order to get
high-quality assertion-checking of the inputs.  In some cases, the error
messages for bad input when instrumented are also more useful than I would
have otherwise gotten, but in some cases they aren't.  Overall, I've
struggled to write generators, and without them, the value proposition
isn't as great.

One other issue I've had, unrelated to generators, is that I'm struggling
to express higher-order type constraints, for example, this function takes
a vector v1 of anything and a vector v2 of anything, but the type of the
things in vector v1 better match the type of the things in vector v2.

What are other people finding?  Do you find it easy/hard to write
generators?  (If you think it's easy, I'd love to know your tricks).  Do
you find it easy/hard to read specs as a form of documentation about the
contract of a function?  Do you find it frustrating that there's no way to
turn on instrumentation of function outputs for manual testing?  Do you
feel your generators are providing sufficient code coverage when exercising
callee functions?

-- 
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.

Reply via email to