clojure-spec

About: http://clojure.org/about/spec Guide: http://clojure.org/guides/spec API: https://clojure.github.io/spec.alpha/clojure.spec.alpha-api.html
Aron 2020-04-13T08:21:23.099100Z

Hi, I would like to do some "spec driven development" in cljs, where should I start? Is it the same for clojure and clojurescript?

2020-04-14T13:56:53.104500Z

I think in general it’s similar. For UI applications the boundries that you want to focus your specs on are different of course. I consider anything coming over http and websockets a good candidate for checking with spec and all of my component props as well. If you’re using Reagent the later is easy because your components are already functions and you can just us s/fdef . Another consideration is I like to keep my specs separate from my other code on the F/E. Instead I write separate spec files that require the namespaces that I’m specing. Then you can make a preloads file that imports those spec files and runs st/instrument to get development-time feedback.

Aron 2020-04-14T14:07:43.104800Z

I am not using reagent because it has no support of modern react, I am using helix.

Aron 2020-04-14T14:09:24.105100Z

Thanks for the note on 'separate', I was just thinking about that, I saw a video with @alexmiller where it was noted to not use these in production and I am not quite sure how to do that. I thought that the compiler would remove these when I build for production and I will not have to maintain two versions of my code

2020-04-14T14:18:24.105300Z

It looks like the defnc macro in helix eventually produces a function with [props ?ref] that you can spec like a Reagent component: https://github.com/Lokeh/helix/blob/master/src/helix/core.clj#L80-L87

Aron 2020-04-14T14:19:57.105600Z

How many years before I can do what you just did @colinkahn ? : D

Aron 2020-04-14T14:20:32.105900Z

I can read the code, but all these ^s and ~ confuse the hell out of me.

Aron 2020-04-14T14:21:53.106100Z

and yeah, I am fairly sure I can spec it, it's more about the context/reducer situation that I am somewhat unsure. I think I can do state transition functions and spec those and then I can create spec for the state as input and output before and after the transition.

2020-04-14T14:24:01.106300Z

The “separate” approach for me works because I agree these are more development-time tools and don’t really belong in my production source code. The compiler I believe will remove most of it (I’ve seen tricks where frameworks using Google Closure features to help with this as well) but I think certain parts of the spec library itself cannot be dead code eliminated (though don’t quote me on that, and probably better to try it yourself). For having two versions, this isn’t necessary. For example: app.components.cljs

(ns app.components)

(defn my-component [props]
  ...stuff)
app.components.specs.cljs
(ns app.components.specs
 (:require [app.components :as c]))

(s/fdef c/my-component
  :args (s/cat ...))

2020-04-14T14:25:50.106500Z

https://clojurians.slack.com/archives/C1B1BB2Q3/p1586873997105600?thread_ts=1586766083.099100&cid=C1B1BB2Q3 You have to go through your “macros” phase 😉

Aron 2020-04-14T14:26:16.106800Z

I haven't even started that... : )

2020-04-14T14:29:00.107Z

This is the preloads feature I was referring too: https://clojurescript.org/reference/compiler-options#preloads Once you have your *.specs namespaces I make a single specs.preload or something that is roughly:

(ns app.specs.preload
  (:require [clojure.spec.test.alpha :as st]
            ; all your spec namespaces here
            [app.component.specs]))

(st/instrument)

Aron 2020-04-15T06:53:27.110300Z

This is somewhat different for shadow-cljs, right?

2020-04-15T15:12:54.121900Z

It’s pretty much the same, you’d specify the preloads in your build defined in shadow-cljs.edn

2020-04-15T15:14:13.122300Z

Actually yeah, it’s under a different key