This question already has an answer here:
Today I had a discussion with a colleague on whether to test or not to test private members or private state in the class. He almost convinced me why it makes sense. This question does not aim to duplicate already existing StackOverflow questions about the nature and reason of testing private members, like: What is wrong with making a unit test a friend of the class it is testing?
Colleagues suggestion was in my opinion a bit fragile to introduce the friend declaration to the unit test implementation class. In my opinion this is a no-go, because we introduce some dependency of tested code to the test code, whereas test code already depends on tested code => cyclic dependency. Even such innocent things like renaming a test class results in breaking unit tests and enforces code changes in tested code.
I'd like to ask C++ gurus to judge on the other proposal, which relies on the fact that we are allowed to specialize a template function. Just imagine the class:
// tested_class.h
struct tested_class
{
tested_class(int i) : i_(i) {}
//some function which do complex things with i
// and sometimes return a result
private:
int i_;
};
I don't like the idea to have a getter for i_ just to make it testable. So my proposal is 'test_backdoor' function template declaration in the class:
// tested_class.h
struct tested_class
{
explicit
tested_class(int i=0) : i_(i) {}
template<class Ctx>
static void test_backdoor(Ctx& ctx);
//some function which do complex things with i
// and sometimes return a result
private:
int i_;
};
By adding just this function we can make the class' private members testable. Note, there is no dependency to unit test classes, nor the template function implementation. In this example the unit test implementation uses Boost Test framework.
// tested_class_test.cpp
namespace
{
struct ctor_test_context
{
tested_class& tc_;
int expected_i;
};
}
// specialize the template member to do the rest of the test
template<>
void tested_class::test_backdoor<ctor_test_context>(ctor_test_context& ctx)
{
BOOST_REQUIRE_EQUAL(ctx.expected_i, tc_.i_);
}
BOOST_AUTO_TEST_CASE(tested_class_default_ctor)
{
tested_class tc;
ctor_test_context ctx = { tc, 0 };
tested_class::test_backdoor(ctx);
}
BOOST_AUTO_TEST_CASE(tested_class_value_init_ctor)
{
tested_class tc(-5);
ctor_test_context ctx = { tc, -5 };
tested_class::test_backdoor(ctx);
}
By introducing just a single template declaration, which is not callable at all, we give the test implementer a possibility to forward test logic into a function. The function, acts on type safe contexts and is only visible from inside the particular test compilation unit, due to anonymous type nature of test context. And the best thing is, we can define as many anonymous test contexts as we like and specialize tests on them, without ever touching the tested class.
Sure, the users must know what template specialization is, but is this code really bad or weird or unreadable? Or can I expect from C++ developers to have the knowledge what C++ template specialization is and how it works?
Elaborating on using friend to declare unit test class I don't think this is robust. Imagine boost framework (or may be other test frameworks). It generates for every test case a separate type. But why should I care as long I can write:
BOOST_AUTO_TEST_CASE(tested_class_value_init_ctor)
{
...
}
If using friends, I had to declare each test case as a friend then... Or end up introducing some test functionality in some common type (like fixture), declare it as a friend, and forward all test calls to that type... Isn't that weird?
I would like to see your pro and cons practicing this approach.
I don't usually feel the need to unit test private members and functions. I might prefer to introduce a public function just to verify correct internal state.
But if I do decide to go poking around in the details, I use a nasty quick hack in the unit test program:
On Linux at least this works because the C++ name mangling does not include the private/public state. I am told that on other systems this may not be true and it wouldn't link.
I used a function to test private class members which was just called TestInvariant().
It was a private member of the class and, in debug mode, was called at the beginning and end of every function (except the beginning of the ctor and end of the dctor).
It was virtual and any base class called the parent version before it's own.
That allowed me to verify the internal state of the class all of the time without exposing the intenals of the class to anyone. I had very simple tests but there is no reason why you could not have complicated ones, or even set it on or off with a flag etc.
Also you can have public Test functions which can be called by other classes which call your TestInvariant() function. Therefore when you need to change inner class workings you do not need to change any user code.
Would this help?
Pros
hack
Cons
friend
test_backdoor
on the production sideAll of the Pros/Cons aside, I think you are best off making some architectural changes that allow better testing of whatever complex stuff is happening.
Possible Solutions
complex
code in the pimpl along with the private member, and write a test for the Pimpl. The Pimpl can be forward declared as a public member, allowing external instantiation in the unit test. The Pimpl can consist of only public members, making it easier to testcomplex
code in it. Put the declaration in a private header ( not part of the libraries public interface ), and test it.friend struct test_context;
, put your test code inside of methods in the implementation ofstruct test_context
. This way you don't have to friend each test case, method, or fixture. This should reduce the likelyhood of someone breaking the friending.I think unit testing is about testing the observable behavior of the class under test. Therefore there is no need to test private parts as they themselves are not observable. The way you test it is by testing whether the object behaves the way you expect it (which implicitly implies that all private internal states are in order).
The reason for not to be concerned about the private parts is that this way you can change the implementation (e.g. refactoring), without having to rewrite your tests.
So my answer is don't do it (even if technically possible to) as it goes against the philosophy of unit tests.
What will follow is not technically speaking a straight answer to your question as it will still make use of the "friend" functionality but it does not require modification of the tested entity itself and I think it addesses the concern of breaking the encapsulation mentioned in some of the other answers; it does though require writing some boilerplate code.
The idea behind it is not mine and the implementation is entirely based on a trick presented and explained by litb on his blog(coupled with this Sutter's gotw for just a little bit more context, at least for me) - in short CRTP, friends, ADL and pointers to members (I must confess that to my dismay the ADL part I still don't get it entirely, but I'm relentesly working in figuring it out 100%).
I tested it with gcc 4.6, clang 3.1 and VS2010 compilers and it works perfectly.
There's a theory that if it's private it shouldn't be tested alone, if it needs so then it should be redesigned.
For me that's Shi'ism.
On some project people create a macro for private methods, just like:
When compiling for test PRIVATE is defined as public, otherwise it's defined as private. that simple.