Testing Private Methods In Cee Plus Plus

TestingPrivateMethodsInCeePlusPlus is a FAQ (Frequently Asked Question).

Quick Answer Think carefully before using private stuff in the tests. If you must, either make the test class a friend (using a forward class declaration), or put the code that must test private stuff in a public member of the class, e.g.

void class_under_test_c::test(void) {}

What follows is a discussion extracted from CppUnit.

(1) Should Private Stuff Be Tested?

This viewpoint is represented by JohnGardner:

I have to comment on this. If the class is designed properly, you shouldn't need to do private testing. If there is any code that isn't exercised via the public interface, why is it there? If the public interface does what it is supposed to do, why do we care about the private implementation details? In most cases the need to test private members indicates the need for refactoring. This is the direction you should head in rather than finding nice ways to break encapsulation.

AndyGlew response:
This is a valid point. However, those with experience with hardware's more formal testability approach will recognize issues of observability and controllability. It is sometimes just plain easier or more convenient to look at private stuff, than to use the possibly slow public interface. However, needing to access private stuff should be considered a CodeSmell - sometimes it cannot be avoided, but it should be if possible.

(2) Make the tester class a friend of the testee

If a forward declaration is used, the testee does not depend on the tester.

(3) Provide public accessors for everything you want to test

But that's exposing private information to the whole world.

(4) Use a pre-processor macro PRIVATE instead of private:

 #ifdef TEST_MODE
 #define PRIVATE public
 #else
 #define PRIVATE private
 #endif

Now you can compile the program without TEST_MODE just to make sure that no access to private stuff is made by the program itself, and then compile with CppUnit with TEST_MODE defined and gain access to everything (this is probably the worst).

(5) #define private public This is sort of like option 4 of redefining private to be public with two big differences : You don't have to use ugly PRIVATE macro all over your code, but you have to #define/#undef the 'private' symbol before/after #including files to be tested. Since you develop tests incrementally it doesn't seem like a big burden.

 #define private public // make sure we have access to private parts
 #include "class_under_test.hh"
 #undef private // restore privacy to private

CPPUNIT_TEST_SUITE_REGISTRATION(CDomDocumentTest); ...

According to the C++ standard, this may result in undefined behaviour, because it creates two different definitions of the same class in different translation units. Therefore you can only use this technique with a compiler that guarantees that it works, and not in portable code. -- NatPryce

AndyGlew comment: I think the undefinedness only applies if the two translation units are linked. If you recompile and link everything with private ifdeffed out, it should work, and vice versa. It's only if the definition is inconsistent that it causes a problem. Nevertheless, it's a dangerous practice.

(6) #define private protected Another way to deal with private members is to replace private with

  #ifdef TESTMODE 
protected:
  #else 
private:
  #endif 
wherever it occurs. Or, equivalently, #define private protected

Then have the tester inherit the testee, this way private member are never turned into public ones and the tester don't have to be declared within the testee, it also makes the setup and clean up easier since the testee is initialized when the tester is initialized

Use Protected, not private

Yet another possibility is to not use private at all, but only to use protected. However, many folks, including BjarneStroustrup, find that protected inheritance is a dangerous thing to have period, and should be avoided.

Use Class Test Methods

Instead of trying to put the test in a separate class, create one or more test methods in the class under test. It is probably a flaw of C++ that all such methods / member functions have access to all private stuff, but they do.


CategoryTesting CategoryCpp


EditText of this page (last edited April 14, 2008) or FindPage with title or text search