I've read a lot o blogs arguing about private methods and testing. Some people say you should not test private methods, they say you should make them public or put those methods in a new class.

But then, what about encapsulation? let's say:

  1. I have this method which is simple enough for not being part of a new class, and
  2. It can be useful only for internal stuff, so there's not a good reason to make it public.

My general rule about methods being public or private is simple, if it's useful outside it's public, if it's useful just inside then it's private. Am I missing something with this logic?


Design For Testing, But Don't Code For Testing

You use private methods to reduce code. Less code is always more stable. Extracting a private method to another class so it can be tested makes more code, and makes something that was in the domain of the class now an external thing.

If a class is used only by one other class. That the two classes are partial representations of a whole class, then you have a problem. While your unit tests are going to pass, they aren't going to pass for long. They are going to break. It's like working on fixing a table thinking it stands on 3 legs when infact there are 4. The 4'th leg is just not within view when you're working on it.

Design for testing means you've created a collection of classes, interfaces and other things that will remain stable as your modify it. There shouldn't be a huge ripple effect when you break something (there can be a ripple cause by dependency, but failure should be horizontal. Not vertical).

A user of a class wants reliabilityfirst. Your unit tests should show that the class is stable under all possible states. You could make every method public and get 100% code coverage. Does this really make it more reliable? No it doesn't.

Think first, what unit tests I need to have to verify this stuff actually works as intended.

Having a private method double_price() doesn't mean it needs to be tested. It's likely called a few dozen times from different parts of the class. It doubles the price, and that happens in lots of places so it's reused code.

Does this method risk stability? If it does then ask yourself "Does the risk justify a different set of unit tests?" If so, then encapsulate and write unit tests for that.

Think Of It Like This.

To build a system you want to use small pieces that you know work. If you take pieces A and B that you know pass unit tests, then creating C using A and B makes C more stable.

Don't Think Like This

I have a system called A. Is it stable? I don't know. Let's open A and rip out B and C. Now I can test A, B and C.

Why is this bad? Because this can happen. A and C pass unit tests but B fails. How can A and C be stable? Because you didn't rip A apart correctly. A is actually unstable because part of it is pretending to be B.

oh man, I think I just gave myself a headache.

| improve this answer | |
  • Another point to keep in mind - if you're making methods public when they don't need to be, then you can hurt performance because you may need to introduce extra checks on inputs. – Phil Lello Mar 7 '16 at 13:02

In a case like you describe, I would keep the method private. Testing (especially unit tests) should give you good coverage of your class without needing to know the implementation. If the tests are too coupled to the implementation (rather than desired behavior) then the class will feel brittle and hard to work with.

If you do your job correctly, your private method should be thoroughly tested (code coverage) indirectly by testing the behavior of your class.

| improve this answer | |

No I would completely agree with you and a similar logic was thought to me in college. We were thought basically, make it private in all cases unless you need to access it from somewhere else.

Many Times I would make a private method as a way to cut down code duplication. Say I have 3 public methods that all at some point need to run similar code. I'm not going to make another public method that is not necessary and possibly dangerous if its a group project, I'm not going to have the code there 3 times making it unmanageable, I'm going to make a private method and call it 3 times, thats basic programming knowledge.

As for not testing it? never in my life would I finish a project without testing a method ... deliberately of course.

I find the statements you've read on blogs to be completely ridiculous, you should stay away from these blogs or authors as they are not programmers.

| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.