On Wed, Dec 21, 2011 at 3:57 PM, Richard <legalize+jeeves@mail.xmission.com> wrote:
[Please do not mail me a copy of your followup]

boost-users@lists.boost.org spake the secret code
<87pqfhijjd.fsf@avasys.jp> thusly:

>Chris Cleeland <chris.cleeland@gmail.com> writes:
>
>> I'm using the boost unit test framework to implement unit tests for
>> code.  I'm wondering if there is a best-practice for doing white-box
>> testing/internal state inspection of types under test.  My hack right
>> now is to strip out "protected" and "private" from the header, but I
>> hold my nose as I do that.

That is what I've come to accept as probably the cleanest possible solution without hacking/redefining "private"/"protected" in production vs. test code (even though it's far from what I would call elegant).
For a class I essentially create a friend in a completely different "test" namespace, the unit tests go in that namespace and are linked against the object files to test them and validate class internals/invariants. The shipping code (headers) always have the 'missing' friend declarations, but as I said it's a 1 line that I've gotten to accept as the least ugly solution until I come across something that's more elegant.
 
>
>I don't use private members in the header file and put a subclass in the
>test implementation that makes the parent class' protected API public.
> [...]

I do this with legacy code, i.e. code that wasn't designed with
testing in mind.

However, I find that I don't need to do this when I practice TDD
because the classes were designed to be testable in the first place.

While I think that's a great idea and it does to an extent make you think about your classes and making sure that they are simple enough to be externally testable, sometimes there are complicated relationships between classes, to test them in isolation, you may have to mock a few classes and replace them with test classes, this eventually leads to having to virtualize methods in order to be able to call them in the test classes without the class under test being aware.
I have found this to cause unnecessary methods having to be virtualized in order to replace concrete objects with test objects in a class being tested, which ended up getting quite messy at times, so I essentially had to settle for the "friend" solution.

Regards,
Ahmed