Should You Unit Test Private Methods Of A Class?

Have you wondered if you have to write unit tests for private methods of a class? In this post, I’ll answer that question for you.

This question is answered with the context of WordPress in mind. But this serves as a general rule, irrespective of the language.

I fell in love, once again, with WordPress so much that I started contributing to few open source projects.

I began my contribution by fixing small bugs. Lately, when I was writing test cases for a WordPress plugin, I had this question, “Should we write unit test case(s) for the private methods of a class?”

I didn’t have an answer for a moment, but then I figured that the private methods are used by the public methods. By writing test cases for the public methods of a class, we cover testing the functionality of the private methods. So the answer my question is ‘No, we don’t have to write unit tests for private methods of a class’.

What Should You Do If A Private Method Warrants Testing?

Even after covering the public method that uses the private method, if your private method warrants test to cover, then you should probably think of breaking the private method into smaller units. The basic rule is that a function must do only one specific thing.

In order to verify my understanding, I did a quick Google search and found that Brian, a software developer, had mentioned the same in his blog.

Author: Maria Daniel Deepak

I'm a Web and WordPress developer who is exploring the minimalist lifestyle. Read more

3 thoughts on “Should You Unit Test Private Methods Of A Class?”

  1. You are facing the dilemma that everyone faces when they start doing unit testing šŸ™‚

    On theory I agree that you shouldn’t test private methods. But sometimes you might face a scenario where it might be easier if you can just test the private method separately instead of trying to test it using the public method especially when you are trying to add tests to a codebase that was already developed without tests in mind or the private methods are just util or helper methods.

    Let me give you an example (overly simplified).

    Let’s say you have two private functions. One which does addition of two numbers and one which does multiplication of two numbers.

    Then there is a public method that takes two arguments and computes the following equation.

    (a + b) + (a * b)

    The pseudo code for your public method would be something like this.

    public function compute($a, $b) {
    $r1 = $this->add($a, $b);
    $r2 = $this->mul($a, $b);
    return $this->add($r1, $r2);
    }

    Now, the tests are going to become complex for the public method to target all the edge cases for the private methods šŸ™‚

    I am not suggesting that you should start testing your private methods, but I am just saying that Unit test is a tool and sometimes taking a practical approach instead of a theoretical one might save you some time, but off course with a compromise. The compromise in this case would be that you can’t freely refactor the private methods of the class without changing the tests.

    My personal opinion is that you should fully understand why a certain guideline, best practise, technical concept, rule or design pattern is recommended and then take a decision keeping the compromise in mind (and also document it) without blindly following it, just for theoretical pureness šŸ™‚

    I have seen code where the developer has taken the “Don’t test private methods” rule to the extreme and has made all private/protected methods as public, just to test them independently šŸ˜‰

    Now that we are done talking about testing private methods, I will give you another similar thing to ponder over. Should you pass member variables of a class as an argument to your private function or should the private function retrieve them from the class directly using this operator?

    What are your thoughts? šŸ™‚

    1. Hello Sudar,

      Thanks for your wonderful and detailed comment. By the way your question seems tricky.

      Anyway, I understand that taking a decision to test private methods is totally based on the scope and objective and not merely by thoery. I have to edit my blog post soon and thanks again, for taking time to correct me. Blogging is such a learning. Great!

      And to answer your question on member variables, being a learner of PHP, I again, think that this decision depends on the scope and the objective.

      For example, this operator would be needed when we assign values to the properties (member variables). And, member variables can be passed as arguments, when the private method is using only the values of the member variables and not assigning them. I’m still learning PHP and this is my understanding so far. Please do correct me if I’m wrong.

      Along the way, I found a good blog post that adds clarity to such skeptical stuffs. I think it is a good read.

      1. And to answer your question on member variables, being a learner of PHP, I again, think that this decision depends on the scope and the objective.

        For example, this operator would be needed when we assign values to the properties (member variables). And, member variables can be passed as arguments, when the private method is using only the values of the member variables and not assigning them. Iā€™m still learning PHP and this is my understanding so far. Please do correct me if Iā€™m wrong.

        Actually my question doesn’t involve PHP at all šŸ™‚ This applies to all object oriented programming languages.

        There are two school of thoughts on this, especially when the member function is not private and you have to test them directly.

        1) If you pass all the values required by the function as parameters, then it becomes easier to setup during testing. You don’t have to setup the entire class, but kind of becomes difficult to manage if other member functions change the member variable.

        2) If you don’t pass the values as parameters, then the methods are tightly coupled with the data structure of the class (which it should), but during testing it becomes difficult, since you have to setup the class and the entire data before you can start testing the method.

        Again there is no right or wrong answer. As you correctly said, it would depend on scope and objective and which compromise you are ready to take šŸ™‚

Leave a Reply

Your email address will not be published. Required fields are marked *