Fork me on GitHub

Is it idiomatic to use spec to validate data with remote service through http request?


@blance I think it's idiomatic to use spec for validating data in a lot of cases. Can you be a bit more specific?


For example, we use to spec to validate (and conform) input arguments to our REST APIs and in some other places either before or after interaction with an external system.


say I have a user id that needs to be an int, normally i would just validate it using int?. i'm just curious does it make sense to also do

(def ::user (s/and int? user-exist?)) 


where user-exist would have to call to an external service to check if user exists


I'd be careful about using predicates that rely on outside systems for your specs. That feels wrong to me.


if you try and use ::user with generators, are you going to be upset if it sends hundreds of thousands of requests to your external service?


Yup. I would say it's worth trying to stick with specs that can be used in generators.


sometimes it's surprising which spec functions use generators too. e.g. instrumentation


i haven't really start looking at generative testing yet


i suppose http request can be mocked during testing?


reading more on the doc,

A key design constraint of spec is that all specs are also designed to act as generators of sample data that conforms to the spec
sounds like I shouldn't be using any non trivial pred that can't easily generate good sample data


You can use non-trivial predicates (and, I think, it is one of the value props of spec), but if you end up using it for generative testing you will have to help that predicate with a custom generator to minimize "Couldn't satisfy such-that predicate after 100 tries" errors ( You can write predicates with side-effects, but as with usual code – try to isolate them from the pure ones, and know all the contexts where those might be used. So checking if user exists is perfectly fine, but probably should be done at a very specific points of the system, separate from checking hypothetical user's structure. Also: "not everything needs to be a spec", as well as "not everything needs to be specced". @blance


that make perfect sense, thanks!


I'm struggling on how to create a generator that returns a constant value


my example is UUID or constant id


(gen/one-of [(s/gen ::uuid) ...])


let's say the constant is 0


I was looking for gen/return