Hi Frantisek!

I can see where this is useful, and the only reason I haven't
implemented something like it for a test-is already is that I don't
expect it would be very commonly used outside of the very specific
case of testing the language itself. Where else, other than a language
specification or a math library, are you going to be testing every
combination of arguments?

Secondly, remember that tests are just functions, with a little extra
metadata. I thought about allowing them to accept arguments, but then
I didn't know how to call them in run-tests. But you can define
ordinary functions and use them in your tests. It turns out to be
pretty easy to define all-all are this way:

(defn all-are [pred & args]
  (doseq [[x y] (combinations args 2)] (is (pred x y))))

(deftest equality
  (all-are = 0 0.0 0M 0/1)
  (all-are #(and (= %1 %2) (not= (class %1) (class %2)))
           (sorted-map :a 1) (array-map :a 1) (hash-map :a 1)))

The only disadvantage to this is that you won't get some of the nice
error reporting features, like individual line numbers, that you get
when you use "is" by itself. But you would have the same problem if
all-all are were a macro.

So I guess, overall, I'm saying you shouldn't feel limited to using
just the basic constructs that the library provides. They're just
building blocks for your own, larger abstractions.  If there's a
particular abstraction that shows up repeatedly in lots of different
contexts, then I'll want to add it to the library.

As for the fate of "are", I've always been a little uncertain about it
because it relies heavily on the templates library. And I've always
been uncertain about templates because they rely heavily on code
walking and code transformation. For example, in early versions of the
lazy branch, "are" didn't work, and I never could figure out why.
Fundamentally, I think anonymous functions are a more robust
abstraction than templates, and my future work will probably rely more
on functions than templates.  Still, several people have said they
like "are", so I wouldn't drop it lightly.

Peace, love, and happy testing...

-Stuart Sierra



On Mar 19, 3:28 pm, Frantisek Sodomka <fsodo...@gmail.com> wrote:
> Hello Stuart & all!
>
> As discussed in this thread:
> test-is: generating and processing testing 
> datahttp://groups.google.com/group/clojure/browse_frm/thread/3e84efefd7c0...
>
> , sometimes it is necessary to test each value against each value. Example
> is zeros-are-equal (as you suggested):
>
> (deftest zeros-are-equal
>   (doall (map (fn [[a b]] (is (= a b)))
>               (combinations [0 0.0 0M] 2))))
>
> Truth is that these combinations are more common than I thought. For
> example, when testing equality of maps (test-equality in data_structures.clj
> in test_clojure), values of maps equal, but their classes are not.
>
> (= (sorted-map :a 1) (hash-map :a 1) (array-map :a 1)) => true
>
> (class (sorted-map :a 1)) => clojure.lang.PersistentTreeMap
> (class (hash-map :a 1)) => clojure.lang.PersistentHashMap
> (class (array-map :a 1)) => clojure.lang.PersistentArrayMap
>
> To test for this property, we can either write down all combinations (as I
> did) or write deftest function for each case (equality and non-equality).
> Each of these seem too verbose to me. I see 2 different solutions:
>
> 1) Allow deftest (new version of it?) to accept parameters:
>
> (deftest each-equals-each [parameter]
>   (doall (map (fn [[a b]] (is (= a b)))
>               (combinations parameter 2))))
>
> This way we could call it:
> (each-equals-each [0 0.0 0M])
> and
> (each-equals-each [(sorted-map :a 1) (hash-map :a 1) (array-map :a 1)])
>
> 2) Create new version of 'are' - 'are-combinations' or more preferably
> 'are-all', which uses 'combinations' in itself:
>
> (are-all (= _1 _2)
>     0 0.0 0M)
> =>
> (is (= 0 0.0))
> (is (= 0 0M))
> (is (= 0.0 0M))
>
> This way we can easily do:
>
> (are-all (= _1 _2)
>     (sorted-map :a 1) (hash-map :a 1) (array-map :a 1) )
>
> and
>
> (are-all (not= _1 _2)
>     (class (sorted-map :a 1))
>     (class (hash-map :a 1))
>     (class (array-map :a 1)) )
>
> or combined? ;-)
>
> (are-all (and (= _1 _2) (not= (class _1) (class _2)))
>     (sorted-map :a 1) (hash-map :a 1) (array-map :a 1) )
>
> Personally, I prefer the second solution. It looks really elegant. The first
> solution - tests with parameters - is useful too and we could use it under
> different conditions.
>
> Thank you, Frantisek
>
> PS: What is the status of 'are' macro? Documentation still says
> "Experimental. May be removed in the future.". Do you have any plans for it?
> I really like it and use it heavily in test-clojure.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to