How or should I test private methods?

Often I would extract methods from blocks of existing code to make things clearer or easier to refactor later. However, these tiny methods should not be part of the public API, therefore I’d like to mark them as private. But this causes 2 problems:

  1. Since these are private, i have to use instance_eval to call them, which leaves me an uneasy feeling.
  2. Since these are inner workings of an object, often they evolve very quickly. So the tests I write for these are more brittle and likely out-of-date quickly.

So my questions are should I write explicit tests for these? If so, other than instance_eval, are there other ways I can write them?

In my opinion, you should not test private methods,but If you need to test them extract for another class.
I do not know if i am correct but I usually use this approach.


(I’ll reply with more detail later. :slight_smile:

Test only what you expose! That means your public methods.

To expand a little on what the others are saying.

It is considered bad practice to test private methods because they make objects less flexible. Your tests will make it harder to refactor, the opposite of what you want. The internal implementation of a particular object should not matter; External behaviour is the only important thing.

Option 1: Your internal methods are not too complex, and their behaviour can be tested through the public methods on the class. Just don’t test the private methods explicitly.

Option 2: Your internal methods are quite complex, and testing their full behaviour through the public methods is annoying. This probably indicates that your class is too complex and needs to be split. How you split it really depends on the class in question so without more information it is hard to advise.

To paraphrase what @mcgain is saying, Why do you want to test the private methods?

It’s probably because you are not confident that the private methods are working by testing only the public methods. This is a smell that suggests that the model is doing more than one thing. Does the model have a single responsibility? What is it?

Do the private methods that you want to test share a responsibility or have common functionality? If so, then they can have their own model. Now the private methods that you wanted to test are public.

A great resource on this subject is Practical Object-Oriented Design in Ruby.