For the last little while, I’ve had a dilemma upon me regarding the testing of private and protected methods. In keeping with the 3 rules of TDD, I wanted every bit of code that I wrote to be preceded by a test that would check that bit of code.
This lead me to the desire to test the private instance methods of a class I was building. I’d never had this come up before, so I started searching. Found some answers on StackOverflow, implemented them and everything was going fine.
Should I Test Private Methods?
Then started to ask myself if I SHOULD be doing this. As I said in the first paragraph, I did this because I wanted to test every little bit of code that I write. Afterwards though, I started to ask myself if that’s really the best way to do it.
Now yes, you do want full test coverage. We have tools like Ruby’s simplecov to ensure that every line of code you write is checked by your tests. However, think about what tests are actually supposed to accomplish. Your tests are supposed to mirror how other developers are going to use your library. They’re not going to call the private methods, they’re going to call the public methods that then call the private methods. So no, you really don’t need to test private methods.
What’s the harm if I want to?
Well, that’s the other question, isn’t it. Maybe you want to be absolutely sure that all your code works, private and public. That’s certainly a capital idea.
However, there are two downsides to directly testing your private methods.
First, comes refactoring. Proper TDD workflow is Red-Green-Refactor. You write your failing tests, you write code that makes it pass the test, then you refactor. Sometimes you refactor over and over again. The reason we do it in this order is so that we can refactor with the certainty that we’re not breaking the code. So, what happens when that refactoring involves changing your tests? Well then, we lose the certainty, and we run a risk of developing test apathy. That’s the last thing you want, in yourself, or your team.
The other reason to not test your private methods directly is for ensuring test coverage. Tools like the previously mentioned simplecov show you parts of your code are covered by tests and what parts aren’t. Test coverage tools are also good for helping you find code bloat. That is, parts of your code that never execute. If you’re testing your private methods directly, they’ll always be covered by tests, which means that they won’t be revealed as code bloat by test coverage tools. However, if you only test your public methods, and everything is covered other than your private method, well, you know you can get rid of it.
With all this in mind, I say DON’T test private methods. Your refactoring will be smoother, your test coverage will be more certain, and you’ll be fighting off test apathy.