ghostwheel

Hassle-free clojure.spec, automatic generative testing, side effect detection, and evaluation tracing for Clojure(-Script) – https://github.com/gnl/ghostwheel
genekim 2018-08-10T23:40:23.000076Z

@clojurians.net I’m late posting this, but just wanted to let you know that last week, I also added Ghostwheel to ClojureScript side of the application — worked on first try. Was immensely helpful. I’m loving it so much, I’m adding it to another Clojure project, with the intent of using it wherever I used to do things like {:pre [(s/valid? map? b) (s/valid? seq? nots)]}. My only comment: when there are spec errors, I was a little surprised that the line number is sometimes missing. I’ll post an example when I next run into it. Keep up the great work!

genekim 2018-08-10T23:49:30.000043Z

Wow, that didn’t take long to get running in new project and generate spec error! (Shows you how badly I need type checking. :) This is what shows up in the rendered web page in ring…

Problem accessing /mock-books. Reason:

    Call to #'bookserver.views/render-book-one-row did not conform to spec:
val: [:tr [:td 273] [:td [:a {:href /books/273} abc_kindle]] [:td [:a {:href /reviews/273} nil]] [:td B0199EW96U] [:td [:a {:href /salesranksgraph/273} link]] [:td 96] [:td -] [:td nil] [:td  ] [:td  ]] fails at: [:ret] predicate: seq?

Ah, I see that in the REPL, it does get printed out at very end…
clojure.lang.ExceptionInfo: Call to #'bookserver.views/render-book-one-row did not conform to spec:|val: [:tr [:td 273] [:td [:a {:href /books/273} xyz_Kindle]] [:td [:a {:href /reviews/273} nil]] [:td B0199EW96U] [:td [:a {:href /salesranksgraph/273} link]] [:td 96] [:td -] [:td nil] [:td  ] [:td  ]] fails at: [:ret] predicate: seq?| {:clojure.spec.alpha/problems [{:path [:ret], :pred clojure.core/seq?, :val [:tr [:td 273] [:td [:a {:href "/books/273"} "xyz_Kindle"]] [:td [:a {:href "/reviews/273"} nil]] [:td "abc"] [:td [:a {:href "/salesranksgraph/273"} "link"]] [:td 96] [:td "-"] [:td nil] [:td " "] [:td " "]], :via [], :in []}], :clojure.spec.alpha/spec #object[clojure.spec.alpha$spec_impl$reify__1987 0x474e94d4 "clojure.spec.alpha$spec_impl$reify__1987@474e94d4"], :clojure.spec.alpha/value [:tr [:td 273] [:td [:a {:href "/books/273"} "YearInWhite_Kindle"]] [:td [:a {:href "/reviews/273"} nil]] [:td "B0199EW96U"] [:td [:a {:href "/salesranksgraph/273"} "link"]] [:td 96] [:td "-"] [:td nil] [:td " "] [:td " "]], :clojure.spec.alpha/ret [:tr [:td 273] [:td [:a {:href "/books/273"} "abc"]] [:td [:a {:href "/reviews/273"} nil]] [:td "abc"] [:td [:a {:href "/salesranksgraph/273"} "link"]] [:td 96] [:td "-"] [:td nil] [:td " "] [:td " "]], :clojure.spec.alpha/failure :instrument, :orchestra.spec.test/caller {:file "views.clj", :line 209, :var-scope bookserver.views/render-book-table, :local-fn fn}}
	at clojure.core$ex_info.invokeStatic(core.clj:4739)
	at clojure.core$ex_info.invoke(core.clj:4739)
	at orchestra.spec.test$spec_checking_fn$conform_BANG___16678.invoke(test.clj:113)
	at orchestra.spec.test$spec_checking_fn$fn__16684.doInvoke(test.clj:125)
	at clojure.lang.RestFn.invoke(RestFn.java:421)
	at bookserver.views$render_book_table$fn__20286.invoke(views.clj:209)
If I could wave a magic wand, the line number would show up at the very top, since it’s the first thing I’m going to look for when there’s an error.

genekim 2018-08-10T23:49:37.000028Z

@clojurians.net ^^

genekim 2018-08-10T23:58:20.000098Z

Just to encourage you: for areas of code I’m changing, switching from {:pre} to ghostwheel is improving my documentation (and my understanding of what I wrote months ago) by leaps and bound. Writing the types is a joy, as well as reading them! @clojurians.net