Testing private methods

In my unit tests, I get errors when attempting to test private or
protected
model methods. I’ve tried adding public :add_assertion to the class
(read
that somewhere) but I still get the same problem.

Anyone have any input on the best way to test these protected methods?

ed

On Aug 24, 2006, at 1:25 PM, Ed Hickey wrote:

In my unit tests, I get errors when attempting to test private or
protected model methods. I’ve tried adding public :add_assertion
to the class (read that somewhere) but I still get the same problem.

Anyone have any input on the best way to test these protected methods?

Two things:

  1. Since they are private, they must be accessed by other methods
    in the class. Theefore, testing the calling methods will, by
    definition, provide a test of the
    private methods.

  2. You could expose the private methods via a public stub in a
    mock object.


– Tom M.

Tom M. wrote:

  1. You could expose the private methods via a public stub in a
    mock object.

One of the things I love about Ruby is its access control system:
performed at runtime for maximum safety, but does not tries to be
totalitarian at all. Calling a private method is easy enough to do it
when
needed but also ugly enough to prevent you overdoing it:

obj.send :my_private_method, arg_foo, arg_bar

Zsombor

Company - http://primalgrasp.com
Thoughts - http://deezsombor.blogspot.com

What’s wrong with not testing private methods explicitly? Either the
said
private methods or the actions that use them should be simple enough to
‘not
be tested’, aka, by testing the action, you are testing the private
method.
From what I’ve learned in Rails testing, whenever tests get ugly (like
hijacking the class protection methods), then you’re doing something
wrong.
Either don’t make private/protected methods, or test those methods by
testing the actions/ methods that use said private methods.

Jason

i wanted to test the protected methods specifically because they are
small
and easier to test. when you test a calling method (say, one that calls
various protected methods), you have to verify numerous return values
and
conditions. It seems like there’s a lot more room for (human) error by
missing a case, value, etc. Testing the methods in a more granular
fashion
just seemed more stabile to me.

ed

If your protected methods are small and easy to test, then they
shouldn’t be
complicating your public method enough to be a bother. I guess I’d like
to
know how complex this protected method actually is. All of my such
methods
are one-liners like getting a name, or doing a quick math calc and thus
do
not add any complexity to the test of my public method.

Jason

Calling a private method is easy enough to do it
when
needed but also ugly enough to prevent you overdoing it:

obj.send :my_private_method, arg_foo, arg_bar

You can also use a singleton method. It’s 3 more lines of code in your
test class and requires no changes in the actual code to be tested

def obj.my_private_method_publicly (*args)
my_private_method(*args)
end

http://mathandprogramming.blogspot.com/2010/01/ruby-testing-private-methods.html


fhinkel

http://mathandprogramming.blogspot.com/

Ed Hickey wrote:

i wanted to test the protected methods specifically because they are
small
and easier to test.

Just test the public interface. If that’s unwieldy, change it.

when you test a calling method (say, one that calls
various protected methods), you have to verify numerous return values
and
conditions.

No. If you really cared about the intermediate values, you’d have made
the methods public. Since you didn’t, the only value worth testing is
the final return value, because that’s the only one that callers have
access to.

It seems like there’s a lot more room for (human) error by
missing a case, value, etc.

That’s why you have tests! Write as many cases as you need.

Testing the methods in a more granular
fashion
just seemed more stabile to me.

It’s actually less stable, because it’s too closely dependent on hidden
implementation details. For the most part, I believe that your tests
should treat the object as a black box (to be sure, there are
exceptions).

ed

Best,
–Â
Marnen Laibow-Koser
http://www.marnen.org
[email protected]