unit testing private methods?

1,029 views
Skip to first unread message

Allen Rohner

unread,
Jun 2, 2009, 11:57:11 PM6/2/09
to Clojure
I have a namespace with some public functions, and some private
functions. I would like to write unit tests for the functions, and put
them in a separate file from the main name space. I would also like to
have an (ns) declaration in my tests file, because the tests require
several libraries. Of course, if I have private methods in namespace
A, I can't call them from namespace B. Right now, it seems I have
several options:

1) put the unit tests in the same file
2) put the unit tests in a separate file, in the same namespace
3) make the private functions public
4) ???

I don't really like the first three options. Ideally, the private
functions would remain private to every namespace except the testing
name space. Is there a good solution for this?

Allen

Stuart Halloway

unread,
Jun 3, 2009, 12:36:21 AM6/3/09
to clo...@googlegroups.com, Stuart Sierra
Hi Allen,

You could write a function that uses the clojure.contrib.with-ns/with-
ns macro to dip into the namespace being tested and return the private
function, assigning it to a local name in the test namespace.

I need this too, and have been meaning to ping the other Stuart about
either (a) adding something like this to test-is, or (b) creating a
new test-helpers library in contrib that would include this function.

Stu

stephaner

unread,
Jun 3, 2009, 9:11:45 AM6/3/09
to Clojure
Hi everyone,

I agree with Stuart, this would be very helpfull.

Thank you,

Stephan

Andrew Wagner

unread,
Jun 3, 2009, 9:22:56 AM6/3/09
to clo...@googlegroups.com
Well, of course this is a classic situation in OO, if you think about it. Googling around may shed some interesting light on the subject. Essentially, the question is: are you sure that's what you want to do? Why not concentrate your unit tests on the public interface in such a way that the private methods get exercised too. Then, when (not if) your implementation changes, your tests shouldn't have to.

Stuart Sierra

unread,
Jun 3, 2009, 10:24:22 AM6/3/09
to Stuart Halloway, clo...@googlegroups.com
Hi Allen, Stu,

I guess my first inclination would be one of:
> 1) put the unit tests in the same file
using the with-test macro, or
> 2) put the unit tests in a separate file, in the same namespace

Stu's suggestion of with-ns would also work. But you don't even need
with-ns. You can refer a private function into the local namespace
like this:

(def private-function (ns-resolve 'other-namespace 'private-function))

You could even write a function that refers all the private symbols of
a namespace:

(defn refer-private [ns]
(doseq [[symbol var] (ns-interns ns)]
(when (:private (meta var))
(intern *ns* symbol var))))

This is slightly evil, and I would never recommend it for any purpose
except unit testing, but there it is.

-Stuart Sierra

Christophe Grand

unread,
Jun 3, 2009, 10:30:39 AM6/3/09
to clo...@googlegroups.com
Stuart Sierra a écrit :

> Stu's suggestion of with-ns would also work. But you don't even need
> with-ns. You can refer a private function into the local namespace
> like this:
>
> (def private-function (ns-resolve 'other-namespace 'private-function))
>

And don't forget the good old @#'other-namespace/private-function to get
the value of any private var :-)


--
Professional: http://cgrand.net/ (fr)
On Clojure: http://clj-me.blogspot.com/ (en)


Stuart Halloway

unread,
Jun 3, 2009, 4:25:35 PM6/3/09
to clo...@googlegroups.com
>> 2) put the unit tests in a separate file, in the same namespace

This works for me, but since it won't work with the normal use/require
idiom, I would like to see a standard convention evolve to make it
easy to read other people's code.

Stu

Reply all
Reply to author
Forward
0 new messages