This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-07-04
Channels
- # announcements (6)
- # babashka (5)
- # beginners (57)
- # biff (6)
- # business (32)
- # clj-together (1)
- # clojars (10)
- # clojure (56)
- # clojure-europe (76)
- # clojure-nl (4)
- # clojure-norway (40)
- # clojure-serbia (1)
- # clojure-spec (5)
- # clojure-uk (10)
- # clojurescript (3)
- # cursive (12)
- # data-science (1)
- # datascript (4)
- # datomic (35)
- # docs (4)
- # emacs (28)
- # events (5)
- # hyperfiddle (9)
- # matrix (1)
- # off-topic (28)
- # practicalli (4)
- # re-frame (14)
- # shadow-cljs (2)
- # testing (5)
gmåning
straw survey : who is using generative testing - if you are, how widely and what constrains its use - if you are not, why not ?
Not using it. Haven't really invested much time in it. I did try it a few years ago with Spec, found some bugs in some time-related code I'd written - it seemed like it had mileage but the nebulousness of Spec's release date put me off leaning on it more. I think in my head I still might go back to it if Spec ever gets a non-alpha release. I'm reluctant to try a different lib though because if I learn that then Spec will come out and suddenly everyone will be using that.
I used it for my MQTT broker and found it useful. I can generate loads of messages really easy and compare them.
@U04V5V0V4 was the difficulty generating good examples because of a lack of features in spec, malli &c or something else ?
tbh it's probably a mindset change. It's fairly simple to create synthetic data for tests and test scenarios that use the data. Putting together something similar for generative tests feels like a bigger hill to climb. For my part, I don't see a lot of worked examples so it's not easy to see the features / benefits.
i've not used it beyond play before, but i'm thinking of an architecture which puts all business logic in pure coeffects -> event -> effects
(with coeffects
and effects
in the re-frame sense) functions and it seems quite amenable to considerable automation, using generative testing to bash the business logic
Cool, I use it for certain things. Like in Calva I use it to test its Clojure lexer. It has helped me immensely to find edge cases. Still finds them on occasion.
I'd find it much more useful to use openapi-spec to generate tests, anyone ever did that? I played around with spec but found it complicated and time-consuming. EDIT: I am using spec for validation and it's good but generators I found complicated

We do some generative testing at work. I talked about it here https://corfield.org/blog/2019/09/13/using-spec/ The hardest part for us was identifying the invariants we wanted to test this way.
I used property based testing in a client project to test individual pieces of a micro services system. These were event based Typescript services. I definitely think it has value, although it requires quite an investment to become productive writing good properties and value generators.
Ohayo
Here's a riddle for you: I'm doing (def x (call-function-which-returns-huge-data-structure))
in my REPL to trigger debug prints, but I'm not seeing the prints. Why?
(I don't know the answer)
If I just do (call-function-which-returns-huge-data-structure)
, I see the prints.
I suppose it has to do with laziness or something equivalent.
Actually, scratch that.
(-> (call-function-which-returns-huge-data-structure)
keys)
returns the keys, but does not print.Maybe there is a lazy part nested somewhere? If so, how do I realise it easily from the top level?
(hat tip @U2BTBFQVC 🙂
No, I'm pretty sure it's lazy seqs.
But yours and @U052XLL3A’s comment gave me an idea; if I bind out or whatever to something other than my repl, perhaps I could achieve what I want.
(def noop-writer
;; *out* needs to be bound to a java.io.writer, so proxy a writer
;;
(proxy [java.io.Writer] []
(close [] nil)
(flush [] nil)
(write
;; ... which politely ignores any calls.
([cbuf] nil)
([cbuf off len] nil))))
(defn realize [v]
(binding [*out* noop-writer]
(doto v pr-str)))
(def x (map prn (range 100)))
(realized? x)
;;=> false
(def x (realize (map prn (range 100))))
(realized? x)
=> true
Thank you so much, this works excellently!
@U04V4KLKC This works for my purposes 🙂
wait, it doesn't 😅 which makes sense, nothing is happening on print
This works, but transforms the data. It's acceptable for my needs.
(defn realize [data]
(walk/postwalk #(cond-> %
(seq? %) vec)
data))
(def x (realize (call-function-which-returns-huge-data-structure)))
It's funny, I recently wrote this last version of realize
under a different name - make-pastable
- as a means to make REPL-copy/pastable data structures (the REPL misunderstands you when you paste a seq, and thinks you're trying to call a function 😉 ), but it works for this other purpose as well.
https://clojurians.slack.com/archives/CBJ5CGE0G/p1688498607442439?thread_ts=1688464878.989189&cid=CBJ5CGE0G Curious if you tried this? Did it work?
For context, I've used it with lazy seqs that were inside a with-redefs
. So eg
(with-redefs [get-something ....]
(realize
(for [e es]
(get-something e))))
@U052XLL3A I see why
(defn realize [v]
(doto v pr-str))
should work, but it doesn't.
(def x (-> (something-that-returns-huge-data-structure)
realize))
;;=> #'my-ns/x
The prints are not happening. But this works:
(def x (->> (something-that-returns-huge-data-structure)
(clojure.walk/postwalk #(cond-> %
(seq? %) vec))))
"something"
"something"
=> #'my-ns/x
@U052XLL3A yes; as I tried to explain, it's a huge function that calls other functions and so on and so forth. I'm trying to print "something"
from one of those subfunctions.
I suppose it has to do with laziness or something equivalent.
yes, this is connected with laziness:
(def x (range))
will not block.It's been a long time since I've thought properly about this stuff.
If I do keys
on the returned structure, it gets me the keys, but still doesn't print.
But I guess this is because the lazy list is nested somewhere in the data structure?
most likely, hard to say without knowing how this datastructure was created
Yes yes, I get that 😛 Not giving you a lot of info here. It's like a big map that has keys of data constructed from various subfunctions, some are probably lazy lists. How would you fully realise a nested data structure without printing?
(pr-str x)
and ignore the output
for example:
(def x (doto (call-function-which-returns-huge-data-structure)
(pr-str)))
this would be the quickest but probably not the most performant solution
Doesn't work
what doesn't work?
Your example code with pr-str
The only thing that triggers the prints so far is to return the data structure to the repl.
I also tried just (def x (pr-str (call-function-which-returns-huge-data-structure)))
, and even (first (pr-str (call-function-which-returns-huge-data-structure))
. They don't trigger the prints either.
oooo I think I know what it is. There is probably a with-out-str
somewhere.
I recall having some trouble with that before, though I don't recall the exact details.
But it's not there from what I can see.
What's curious is that if I eval x
after (def x (pr-str (call....
, I get the prints as part of the returned string.
Before the actual print of the data structure.
btw, what are you trying to get?
What do you mean? I just want to print some data from one of the subfunctions when calling the main function.
Without having the huge return value flooding my REPL 🙂
instead of printing you can created temporary vars or use tap> in combination with some viewer
"create temporary vars" -> like (def x...
? Or something else?
oh I getcha. Create a var of what I wanted to print instead of printing it.
You are so right 🙂
But I still want to understand why this isn't working. I can't expect you or others to find out, though, the code is a bit involved, and freely sharing it would require quite a bit of refactoring.
I just thought there might be a general reason/solution
printing is a side effect. in general you want to avoid having side effects in lazy calls because they will not be executed in time you wanted but in time they are requested.
(def x (map #(doto % (prn)) (range))
for example
Sure 🙂 I thought there might be some way to force full realisation apart from actually returning the value to the REPL, though.
coincidentally your desired side effect also using the same out as pr-str. That is why there wasn't anything in the repl
Maybe there is a lazy part nested somewhere? If so, how do I realise it easily from the top level?