I know that this is a debated practice, but let’s suppose that this is the best option for me. I am wondering about what is the actual technique to do this. The approach that I see is this:
1) Make a friend class that of the class who’s method I want to test.
2) In the friend class, create a public method(s) that call the private method(s) of the tested class.
3) Test the public methods of the friend class.
Here is a simple example to illustrate the above steps:
#include <iostream>
class MyClass
{
friend class MyFriend; // Step 1
private:
int plus_two(int a)
{
return a + 2;
}
};
class MyFriend
{
public:
MyFriend(MyClass *mc_ptr_1)
{
MyClass *mc_ptr = mc_ptr_1;
}
int plus_two(int a) // Step 2
{
return mc_ptr->plus_two(a);
}
private:
MyClass *mc_ptr;
};
int main()
{
MyClass mc;
MyFriend mf(&mc);
if (mf.plus_two(3) == 5) // Step 3
{
std::cout << "Passed" << std::endl;
}
else
{
std::cout << "Failed " << std::endl;
}
return 0;
}
Edit:
I see that in the discussion following one of the answers people are wondering about my code base.
My class has methods that are called by other methods; none of these methods should be called outside the class, so they should be private. Of course they could be put into one method, but logically they are much better separate. These methods are complicated enough to warrant unit testing, and due to performance issues I will very likely have to re-factor these methods, hence it would be nice to have a test to make sure that my re-factoring didn’t break anything. I am not the only one working on the team, though I am the only one who is working on this project including the tests.
Having said the above, my question was not about whether it is a good practice to write unit tests for private methods, though I appreciate the feedback.
3
An alternative to friend (well, in a sense) that I use frequently is a pattern that I’ve come to know as access_by. It’s pretty simple:
class A {
void priv_method(){};
public:
template <class T> struct access_by;
template <class T> friend struct access_by;
}
Now, suppose class B is involved in testing A. You can write this:
template <> struct access_by<B> {
call_priv_method(A & a) {a.priv_method();}
}
You can then use this specialization of access_by to call private methods of A. Basically, what this does is put the onus of declaring friendship into the header file of the class that wants to call A’s private methods. It also lets you add friends to A without changing A’s source. Idiomatically, it also indicates to whoever reads the source of A that A does not indicate B a true friend in the sense of extending its interface. Rather, the interface of A is complete as given and B needs special access into A (testing being a good example, I’ve also used this pattern when implementing boost python bindings, sometimes a function that needs to be private in C++ is handy to expose into the python layer for the implementation).
1
If it’s hard to test, it’s badly written
If you have a class with private methods complex enough to warrant their own test, the class is doing too much. Inside there is another class trying to get out.
Extract the private methods that you want to test into a new class (or classes) and make them public. Test the new classes.
In addition to making the code easier to test, this refactoring will make the code easier to understand and maintain.
4
You shouldn’t be testing private methods. Period. The classes using your class only care about the methods that it provides, not the ones it uses under the hood to work.
If you’re worrying about your code coverage, you need to find configurations that allow you to test that private method from one of the public method calls. If you can’t do that, what’s the point of having the method in the first place? It’s simply unreachable code.
26
There are a few options to do this, but keep in mind that they (in essence) modify the public interface of your modules, to give you access to internal implementation details (effectively transforming unit testing into tightly coupled client dependencies, where you should have no dependencies at all).
-
you could add a friend (class or function) declaration to the tested class.
-
you could add
#define private public
to the beginning of your test files, before#include
-ing the tested code. In case the tested code is an already-compiled library though, this could make the headers no longer match already compiled binary code (and cause UB). -
you could insert a macro in your tested class and decide at a later date what that macro means (with a different definition for testing code). This would allow you to test internals, but it would also allow third party client code to hack into your class (by creating their own definition in the declaration you add).
Here’s a questionable suggestion for a questionable question. I don’t like the coupling of friend as then released code has to know about the test. Nir’s answer is one way to alleviate that, but I still don’t much like changing the class to conform to the test.
Since I don’t rely on inheritance often, I sometimes just make the otherwise private methods protected and have a test class inherit and expose as needed. The reality is that the public API and the testing API can differ and still be distinct from the private API, which leaves you in sort of a bind.
Here’s a practical example that’s of the sort I resort to this trick for. I write embedded code, and we rely on state machines quite a bit. The external API doesn’t necessarily need to know about the internal state machine state, but the test should (arguably) test conformance to the state machine diagram in the design doc. I might expose a “current state” getter as protected and then give the test access to that, allowing me to test the state machine more fully. I often find this type of class hard to test as a black box.
1
You can write your code with lots of workarounds to stop you having to use friends.
You can write classes and never have any private methods at all. All you need to then do is make implementation functions within the compilation unit, let your class call them and pass in any data members they need to access.
And yes it will mean you can change the signatures or add new “implementation” methods without changing your header in the future.
You have to weigh up though whether or not it is worth it. And a lot will really depend on who is going to see your header.
If I’m using a 3rd party library I’d rather not see friend declarations to their unit testers. I don’t want to build their library either and have their tests run when I do. Unfortunately too many 3rd party open source libraries I have built do that.
Testing is the job of the writers of the library, not its users.
However not all classes are visible to the user of your library. Lots of classes are “implementation” and you implement them the best way to ensure they work properly. In those, you may still have private methods and members but want unit testers to test them. So go ahead and do it that way if that will lead to robust code quicker, that is easy to maintain for those who need to do so.
If the users of your class are all within your own company or team, you can also relax a bit more about that strategy, assuming it’s allowed by your company’s coding standards.