Fork me on GitHub
#clojure-spec
<
2019-05-29
>
Chris Reyes01:05:36

I’m interested in using spec (for the first time) for a side project I’m working on. Where should I put the spec definitions? (Or is that a controversial question?)

Chris Reyes01:05:33

I found this https://stackoverflow.com/questions/37942495/where-to-put-specs-for-clojure-spec But I’m not sure they came to a consensus in any of the answers/comments. (Or maybe I’m not sure how to interpret it because I’m still pretty new to spec)

seancorfield01:05:47

@chrisreyes Most people tend to put data specs in their own namespace, possibly with a few utilities for processing that data, but put function specs next to (above) the functions to which they apply.

seancorfield01:05:26

If you want specs to be "optional" for some functions, it makes sense to put them in a separate namespace, so that users can decide whether to load them or not.

Chris Reyes01:05:53

Okay, thanks!

seancorfield01:05:26

There is no "right way" or "wrong way" -- whatever is most convenient/makes the most sense.

seancorfield01:05:20

When I added function specs to next.jdbc recently, I put them all in a separate namespace, so users could choose whether to use them or not https://github.com/seancorfield/next-jdbc/blob/master/src/next/jdbc/specs.clj

seancorfield01:05:05

That ns actually contains fdefs for two other namespaces within the next.jdbc project, just because that was the most natural/convenient way to set things up.

seancorfield01:05:31

But having fdefs separate isn't as common as having s/defs for data separate.

seancorfield01:05:42

Part of the issue is that specs can serve a lot of different purposes. They can be used for testing in several ways. They can be used to support development (`st/instrument` for example). They can be used in production for data validation (and other things).

hlolli09:05:30

What's & rest in spec. I want to spec [:a :B :C :D] and make sure that first is :a and the rest can by of any amount of any type? (s/cat :need-a ::need-a (&rest?))

djtango09:05:45

(s/cat :need-a ::need-a :rest (s/* any?))

djtango09:05:42

the nested s/* (and other regex ops) is flattened out by default so that doesn't mean [:a [:b ...]]

hlolli09:05:07

ahh I see 🙂 thanks dj! Still after 2 years of spec, these basics are still troubling me

djtango09:05:47

that one definitely requires "grokking"

hlolli09:05:55

yes I would have expected a nested sequence for that

djtango09:05:09

I guess with a lisp hat on you would expect it to nest, but if you were trying to imagine expressing regex via s-expressions it would look like that too so 🤷

👍 1
djtango09:05:59

s/tuple behaves how you might expect iirc

djtango09:05:22

Do people do generative testing over side-effectful code and/or integration tests? I feel it is nice to be able to put an fdef spec over an API endpoint on a webserver (e.g. required params and possible responses) but am unconvinced setting up the check as it starts becoming a bit like a super verbose example test. I suppose instrument with :stub option could work but I'm trying to find a nice way of tying fdefs into integration tests...

holyjak09:05:00

Speaking about integration / system tests, these talks https://lispcast.com/testing-stateful-and-concurrent-systems-using-test-check/, https://youtu.be/zjbcayvTcKQ and Datomic Simulat could be of interest. Regarding side-effects, I guess it depends on their kind. Some you certainly want to avoid when testing. (x with datmoic, you can use an "in-memory" local copy of the DB and never "commit" / transact into the original DB yet have everything there for verification.

djtango10:05:53

thanks for sharing

djtango10:05:56

will take a look!

djtango10:05:06

alas we're not using Datomic at work though