This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-08-15
Channels
- # announcements (9)
- # babashka (1)
- # beginners (1)
- # calva (7)
- # cider (13)
- # clj-kondo (2)
- # cljsrn (1)
- # clojure (40)
- # clojure-europe (2)
- # clojure-spec (9)
- # clojure-uk (1)
- # cursive (4)
- # datomic (2)
- # etaoin (1)
- # fulcro (4)
- # honeysql (3)
- # lsp (43)
- # malli (7)
- # music (1)
- # nbb (6)
- # off-topic (5)
- # polylith (8)
- # protojure (1)
- # re-frame (6)
- # react (17)
- # reagent (63)
- # releases (1)
- # shadow-cljs (8)
- # testing (8)
- # tools-deps (1)
- # vim (8)
Does anyone have recommendations for testing with sets but producing an order? e.g. (string/join "," #{"a" "b"})
and you want to test that the result is either "a,b" or "b,a"? (but obviously the combinations get bigger if your set is 3, 4, etc.)
So, for a set of size N
it would test for all N!
permutations?
Can you give an example for a larger N
where you define the expected results? I imagine it won't be hard-coding values like "a,b"
but instead would be something generative. And if so, it might either become an obvious case of testing 1 = 1
or provide some additional useful information.
I'm not interested in generative testing here. I mean only that for:
(is (= "a,b" (string/join "," #{"a" "b"})))
Is an invalid test. It should instead be:
(is (#{"a,b" "b,a"} (string/join ...)))
But for #{"a", "b", "c"}
, etc. it gets annoying.By "generative" I meant that you would write some code to generate "a,b"
and not that you would generate random data.
In the case of string/join
it 100% feels like testing 1 = 1
, because I imagine such "a,b"
value generation would use string/join
itself.
Ah, I see. I'm quite tired, apologies. I suppose I could implement a version of the tested function which could combine with combinatorics to generate ordered results. That might not be a useful function for testing though.
https://github.com/clj-commons/ordered is my only other idea.
I don't know a thing about what code you currently have, so it's just a random guess, but perhaps that functionality that you want to test could be split into two - one that deals with something ordered, like vectors and lists, and the other that processes sets, turns them into something ordered that's intended to be fed into that first part? That way, you could test these two things separately - it should make testing much simpler.
The idea was to have a consistent data-structure for performing operations on. I'm representing CSPs as data. One of the operations is merging, which requires sets. High performance is a goal though, so switching between data types isn't something I'm keen on.
then sort before passing it to a function OR reverse the rsult of that function back into a set (like splitting on commas in a string/join(
@U3JH98J4R it's set->string not set->set.
I would try to improve that comparator though:
user=> (sorted-set-by #(compare (str %1) (str %2)) 1 "1")
#{1}
Data which we know nothing about. ;) My intention was to only point out that the comparator is not to be used as is blindly.
well their example was #{:none "ws:"}
- thats what i was going off of - still technically nondeterministic for strings starting with :, but 🤷
In the past I’ve liked to compare by type, then by value:
(def cmp
(reify java.util.Comparator
(compare [_ a b]
(if (= (class a) (class b))
(compare a b)
(compare (str (class a)) (str (class b)))))))
Then I use sort-by
on the set, though a sorted-set-by
can also be used:
(is (= "a,b" (string/join "," (sort-by identity cmp #{"a" "b"}))))
(it’s a little annoying to start with (sort-by identity...)
, but than can be turned into a function easily)Asami actually needs to sort like this, since it has a tree structure (on disk) that can contain various types, and so I have to sort by type first. (supported types have a bit-pattern, and so I sort on that, and not by type names)
They’re a little verbose (as shown), but flexible, and you only need to define it the once.
in what context are you referring to it?
(defn to-namespaced [ns un-namespaced-thing]
(if (symbol? un-namespaced-thing)
(symbol ns (name un-namespaced-thing))
(keyword ns (name un-namespaced-thing)))))
(def foo (partial to-namespaced "some.path.to.bar.foo"))
(foo :abc) ; => :some.path.to.bar.foo/abc
it really depends a lot on what you're actually trying to do
if you are getting hung up on aliasing namespaced keywords for namespaces that don't exist, the most common approach right now is to use create-ns
and alias
to construct a non-loaded runtime namespace
this is actually exactly what I'm working on for Clojure 1.11 right now so there will be another option (at some point)