test-is: generating and processing testing data

5 views
Skip to first unread message

Frantisek Sodomka

unread,
Jan 28, 2009, 4:21:31 PM1/28/09
to Clojure
Hello, I have suggestion about clojure.contrib.test-is.

It is useful and sometimes necessary to generate testing data.
Currently, data can be generated by a piece of code and passed to an
'is' function. For example, I want to test for equality of many
things, to see if each is equal to each:

(use 'clojure.contrib.combinatorics)
(use 'clojure.contrib.test-is)

(deftest each-is-equal-to-each
(let [data [0 0.0 0M]
test-data (combinations data 2)]
(doseq [td test-data]
(is (apply = td)))))

Now, I can easily extend 'data' to do more tests (e.g. byte 0, float
0, ...). This will work, but it is not as readable as I would like it
to be.

Another approach would be to allow 'are' macro to accept generated
testing data:

user=> (combinations [0 0.0 0M] 2)
((0 0.0) (0 0M) (0.0 0M))
user=> (apply concat (combinations [0 0.0 0M] 2))
(0 0.0 0 0M 0.0 0M)

(are (= _1 _2)
(apply concat (combinations [0 0.0 0M] 2)))


Older style of tests could be then rewritten as:

(are (= _1 _2)
3 (+ 1 2)
0 (+ -1 1))

becomes

(are (= _1 _2)
(list
3 (+ 1 2)
0 (+ -1 1)))

or nicer:

(are (= _1 _2)
[3 (+ 1 2)
0 (+ -1 1)])

Comments welcome, Frantisek

Frantisek Sodomka

unread,
Jan 28, 2009, 5:29:04 PM1/28/09
to Clojure
Oops, error. Sequence passed to 'are' cannot be evaluated => use
quoted list '( or quoted vector '[ ...

(are (= _1 _2)
'(3 (+ 1 2)
0 (+ -1 1)))

Hm... Since 'are' is basically creating bunch of 'is' tests, I wonder
how to also add a description message for each test. Thinking along
the lines:

(are (= _1 _2)
'(3 (+ 1 2) "should be 3"
0 (+ -1 1) "-x + x = 0"))

(are (is (= _1 _2) _3)
'(3 (+ 1 2) "should be 3"
0 (+ -1 1) "-x + x = 0"))

(do-parse (is (= _1 _2) _3)
'(3 (+ 1 2) "should be 3"
0 (+ -1 1) "-x + x = 0"))

Frantisek

Stuart Sierra

unread,
Jan 28, 2009, 10:52:41 PM1/28/09
to Clojure
Hi Frantisek,

I think I understand what you're looking for here, but I don't see how
to make it work. If "are" could be applied to a generated list, then
it would have to evaluate its arguments, which is a pretty fishy thing
for a macro to do. (But possible -- check out clojure.contrib.apply-
macro). Here's how I would write this sequence of assertions:

(deftest zeros-are-equal
(doall (map (fn [[a b]] (is (= a b)))
(combinations [0 0.0 0M] 2))))

To answer your other question, if you want a message on each
assertion, just use "is". That's why I've never been crazy about
"are", I feel like it encourages too much succinctness. You also lose
accurate line numbers in error reports.

But if you want, you can use "do-template" in
clojure.contrib.template, which is how "are" is implemented.

(deftest my-test
(do-template (is (= _1 _2) _3)
4 (+ 2 2) "simple arithmetic"
5 (+ 2 2) "bad arithmetic"))

-Stuart Sierra

Frantisek Sodomka

unread,
Jan 29, 2009, 5:59:56 AM1/29/09
to Clojure
Thank you for explanation. I will use "is" for tests with messages.
Otherwise, I am quite happy with "are" macro. It really helps with not
repeating myself.

I created 3 new issues and added 2 patches:
http://code.google.com/p/clojure-contrib/issues/list

Issue for sequences is to inform that I am working on it. Too sad, I
cannot add file/patch to it later. (Sorry, I didn't know, just had to
try.)

If somebody wants to look at them and apply patches, I would be
excited :-)

Frantisek

Frantisek Sodomka

unread,
Jan 29, 2009, 9:18:35 AM1/29/09
to Clojure
Patch for testing sequences attached!  ;-)

Frantisek
test-sequences.patch
Reply all
Reply to author
Forward
0 new messages