This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-03-06
Channels
- # babashka (60)
- # beginners (36)
- # clj-kondo (29)
- # clojure (91)
- # clojure-dev (18)
- # clojure-europe (12)
- # clojure-nl (1)
- # clojure-norway (11)
- # clojure-uk (5)
- # clojuredesign-podcast (8)
- # clojurescript (40)
- # core-typed (74)
- # data-science (8)
- # datomic (9)
- # emacs (22)
- # events (5)
- # fulcro (56)
- # gratitude (3)
- # hyperfiddle (11)
- # lsp (6)
- # malli (36)
- # meander (23)
- # off-topic (50)
- # polylith (4)
- # portal (10)
- # reitit (4)
- # schema (1)
- # shadow-cljs (66)
- # squint (3)
- # tools-deps (16)
I wrote some tests like this to apply a different test to each key of a map:
(let [mymap {:key1 5 :key2 10 :key3 "foo"}]
(clojure.test/are [f k] (f (get mymap k))
#(= 5 %) :key1
#(< 9 %) :key2
string? :key3))
However ChatGPT thinks it's bad practice:
> This usage is quite clever because it allows you to compactly specify a series of tests that apply different predicates to different map entries. However, it's worth noting that this is a somewhat unconventional use of clojure.test/are
, which is generally used to apply the same test logic to different inputs. While this approach works and is concise, it might be less clear to others maintaining your code, especially if they expect clojure.test/are
to be used in the standard way for repetitive tests with the same logic.
> Always consider the readability and maintainability of your code, especially in team environments or when others might be reading your code later.
Is it OK or should I listen to ChatGPT?hm maybe I should try using spec or something
I would say "you shouldn't listen to ChatGPT" but I also don't think this is a readable test...
It looks like a contrived example. What are you really trying to test? Maybe Spec is what you want (but it's hard to tell from your question).
My preferred testing library is Expectations (the clojure.test
compatible version) so I would write:
user=> (require '[expectations.clojure.test :refer [expect more-of]])
nil
user=> (expect (more-of {:keys [key1 key2 key3]}
5 key1
#(< 9 %) key2
string? key3)
{:key1 5 :key2 10 :key3 "foo"})
true
user=>
And if you have a Spec, you could just write (expect ::my-spec {:key1 5 :key2 10 :key3 "foo"})
I'm trying to test the response map of a ring handler
We use a combination of Spec and Expectations for that at work.
OK I'll look into expectations
(defexpect good-fetch
(expect ::good-response
(api-get "members/self/activity"
(auth-token "derekpope" "pope"))))
(s/def :ok/http-status #{200})
(s/def ::good-response (s/merge ::act/activity
(s/keys :req-un [:ok/http-status])))
Another Expectations/Spec test at work:
(s/def ::notifiable #{:ok :last})
(defexpect user-should-receive-tests
(let [db-spec (-> test-system :database :pooled-db)
peter (field/as-user db-spec 1)]
(expecting "immediate yes"
(expect ::notifiable
(from-each [note [:like :message :view]]
(let [field (get settings/legacy-settings note)]
(sut/user-should-receive test-system (assoc peter field 1 :searchable true)
:now note)))))
...
There's #C2L9MU2RY if you get stuck...
Yes. the README doesn't justify why Expectations is better than raw clojure.test
. But I guess I'll have to try it and find out.
Also Sean I already use so many of your libraries you're taking over my codebase XD
Well, I didn't write the original Expectations or HoneySQL (or tools.cli or java.jdbc or java.data...) - I just took over maintenance since they were useful libraries:grin:
I don’t think ChatGPT is right here (or ever) except by accident, so i won’t speak to that. I think are
is an anti-pattern. It loses line numbers, it isn’t any more readable than doseq
with is
, and is prone to gotchas (accidentally nesting is
calls).
Expectations is a good library (i use it extensively) but i personally find doseq
more readable than from-each
.
Hey I trained chatgpt to convert HugSQL to HoneySQL the other day. Probly svaed me about 2 hours.
i'm glad it worked out for you. i think it's wrong here to say that using a function is un-idiomatic. are
is simply a templating macro, and there are no assumptions about how it should be used.
Yes I didnt agree with it on that either.
@U043HLWSYUQ Re: README -- I'm curious if anything on this page would satisfy the "why is this better than raw clojure.test
?" question: https://clojure-expectations.github.io/index.html
If so, I'll add some of those examples.
(I try hard not to say why my library is "better" than someone else's but I can see why potential users might want that stated, rather than just reading examples and inferring it)
I guess the stuff in the "More" section does explain the additional features
I think the primary issue is that "clojure.test for Expectations" expects (heh) the reader to know what Expectations is and why it's useful and then why it would be doubly useful to have with "clojure.test"
> This library brings expect
, more
, more-of
, etc from Expectations into the clojure.test
world to be used instead of (or in addition to) the familiar is
macro.
without knowledge of those macros, what does this actually do for the user?
Fair enough. I'll open an issue...
the introduction contains a bit > ... and this might be one if the biggest advantages expectations has over clojure.test ... https://clojure-expectations.github.io/introduction.html
Feel free to add more notes to https://github.com/clojure-expectations/clojure-test/issues/33
Cool. Maybe once I learn Expectations I can help write something up.
Off the top of my head, a pitch paragraph might say something like:
> The library Expectations is a test framework that includes many useful assertion macros. However, it is incompatible with Clojure's built-in testing library clojure.test
, making it hard to integrate with existing tooling.
> This is an implementation of the assertions from Expectations without the baggage of replacing clojure.test
. expect
is multi-faceted, doing x, y and z. in
and from-each
can do destructuring and looping directly within an assertion. etc etc
and then the actual examples can be specific and descriptive
rereading the whole README, i think it actually contains most of this already, it's just spread out and piecemeal. Adding a more descriptive intro to the top would cover that ground nicely
glad to help! i've put expectations to great use in splint