Python Unit Testing – Why Testing Private Methods is Bad Practice

methodspythonunit testing

Context:

I am currently working on a small project in Python. I commonly structure my classes with some public methods that are documented but mainly deal with the high level concepts (what a user of the class should know and use), and a bunch of hidden (starting with underscore) methods which are in charge of the complex or low level processing.

I know that tests are essential to give confidence in the code and to ensure that any later modification has not broken the previous behaviour.

Problem:

In order to build the higher level public methods on a trusted base, I generally test the private methods. I find it easier to find whether a code modification has introduced regressions and where. It means that those internal tests can breake on minor revisions and will need to be fixed/replaced

But I also know that unit testing private method is at least a disputed concept or more often considered as bad practice. The reason being: only public behaviour should be tested (ref.)

Question:

I do care about following best practices and would like to understand:

  • why is using unit tests on private/hidden methods bad (what is the risk)?
  • what are the best practices when the public methods can use low level and/or complex processing ?

Precisions:

  • it is not a how to question. Python has not true concept of privacy and hidden methods are simply not listed but can be used when you know their name
  • I have never been taught programming rules and patterns: my last classes are from the 80's… I have mainly learned languages by trial and failure and references on Internet (Stack Exchange being my favourite for years)

Best Answer

A couple of reasons:

  1. Typically when you're tempted to test a class's private method, it's a design smell (iceberg class, not enough reusable public components, etc). There's almost always some "larger" issue at play.

  2. You can test them through the public interface (which is how you want to test them, because that's how the client will call/use them). You can get a false sense of security by seeing the green light on all the passing tests for your private methods. It is much better/safer to test edge cases on your private functions through your public interface.

  3. You risk severe test duplication (tests that look/feel very similar) by testing private methods. This has major consequences when requirements change, as many more tests than necessary will break. It can also put you in a position where it is hard to refactor because of your test suite...which is the ultimate irony, because the test suite is there to help you safely redesign and refactor!

A tip if you're still tempted to test the private parts (don't use it if it bothers you, and YMMV, but it has worked well for me in the past): Sometimes writing unit tests for private functions just to make sure they're working exactly how you think they are can be valuable (especially if you are new to a language). However, after you're sure they work, delete the tests, and always ensure that the public facing tests are solid and will catch if someone makes an egregious change to said private function.

When to test private methods: Since this answer has gotten (somewhat) popular, I feel obligated to mention that a "best practice" is always just that: a "best practice". It doesn't mean you should do it dogmatically or blindly. If you think you should test your private methods and have a legitimate reason (like you're writing characterization tests for a legacy application), then test your private methods. Specific circumstances always trump any general rule or best practice. Just be aware of some of the things that can go wrong (see above).

I have an answer that goes over this in detail on SO which I'll not repeat here: https://stackoverflow.com/questions/105007/should-i-test-private-methods-or-only-public-ones/47401015#47401015