From: Carlos Moreno on
Ulrich Eckhardt wrote:

>>What I have in mind is debugging/testing (QA kind of
>>testing). Having client code (the "test protocol")
>>access to private data members gives you more flexibilty
>>in terms of easily creating test case scenarios.
>
> [dangers of various ways of changing private to public]
>
> Carlos, you could for every class Foo have a friend class
> Foo_UnitTest, which requires neither hacks nor changes to
> any code.

Well, after hearing the suggestion from you and from Alf,
yes, it feels like "DUH!" :-)

At least the question did trigger an interesting discussion
(with little practical value, at least with respect to my
original intent, but still interesting)

Cheers,

Carlos
--

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Dave Steffen on
"Jiang" <goo.mail01(a)yahoo.com> writes:

> Ulrich Eckhardt wrote:
> > Carlos Moreno wrote:
> > > What I have in mind is debugging/testing (QA kind of
> > > testing). Having client code (the "test protocol")
> > > access to private data members gives you more flexibilty
> > > in terms of easily creating test case scenarios.
> > [dangers of various ways of changing private to public]
> >
> > Carlos, you could for every class Foo have a friend class
> > Foo_UnitTest, which requires neither hacks nor changes to
> > any code.
> >
>
> Well, since we can not add friend class Foo_UnitTest without
> touch the class Foo, the above method is quite expensive, isn't it?
> Also it is possible that someone will use the class Foo_UnitTest
> for other purposes.
>
> BTW I really do not see why the replacement is necessary.
>
> 1. For debugging:
>
> Since the debugger is part of the implementation, the access
> control should not be an issue. All the unspecified behaviors
> will become perfectly well-defined behaviors, provided we
> stay with the same compiler/debugger.
>
> 2. For unit testing:
>
> Also I do not see the benefits for unit testing while all the objects
> will be teared up. All we need to test are the public interfaces
> and internal state probing will introduce unnecessary
> dependencies between the test-cases and classes.
> Logger/analyzer utilities can be used if the internal states are
> really necessary.

(I started a thread on this topic recently on Boost-users.) The
situation I have is a class, with a public interface; but the
heavy lifting is done by private methods, that implement some
extremely non-trivial mathematics.

1) If the public interface is something that's hard to fake up for
unit testing (i.e. involves BigHonkinHairyClasses, to coin a
phrase from Scott Meyers), the cost of hooking up and maintaining
a unit test that talks to the public interface may be
prohibitive. (Alas, our code base has this problem in spades.)

2) Unit tests of the public interface don't do a good job of
pinpointing math errors; an incorrect answer out of the public
interface could result from a mistake anywhere in the math code.
Therefore, it's much preferable to unit test the private methods
directly.

3) It's much, much easier to test corner cases of mathematical
algorithms directly, as opposed to trying to come up with a
BigHonkinHairyClass object with just the right internal state to
poke at a math algorithm in a particular way.

(2 and 3 really amount to a desire to do "white box"-ish unit
tests.)

Responses on the Boost Users list included to:

A) Do the "friend class Tester" thing, as Ulrich Eckhardt said
above. Involves adding a friend declaration to classes, which may
not be possible. Also has problems under some circumstances
(pimpl idioms...)

B) Do the "#define private public" thing as discussed in this
thread. Evil, but carefully contained, fed, and taken-for-a-walk-
twice-daily evil. :-)

C) Do the "Inherit from the class and change the visibility,
and/or add interface to make the class' guts available for
testing" thing, proposed by Jason Aubrey. Requires using
"protected" instead of "private", which has other implications,
and may not be possible.

D) Break the complex mathematical innards out into a separate
class, that exposes them for use. (I think David Abrahams
advocated this approach.)

Personally, I think A frequently works, and isn't too ugly to live
with.

D is a nice ideal, and I'll go there if I can. Given the code base
I'm already working with, that kind of redesign will seldom be
practical (alas).

Alas, B is evil, but it's the only idea I've gome up with, or heard
from anybody else, that allows unit tests access to class' innards,
with _no_ change to class design or implementation.

----------------------------------------------------------------------
Dave Steffen, Ph.D.
Software Engineer IV Disobey this command!
Numerica Corporation - Douglas Hofstadter
dgsteffen at numerica dot us


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Carlos Moreno on
{ I apologize if mistaken / too sensitive (being a fairly new moderator
for clc++m), but there seems to be an (off-) topic drift here, towards
general language-independent sofware testing techniques. Please keep
this related to C++ in follow-ups. -mod/aps }

Jiang wrote:

> 2. For unit testing:
>
> Also I do not see the benefits for unit testing while all the objects
> will be teared up. All we need to test are the public interfaces
> and internal state probing will introduce unnecessary
> dependencies between the test-cases and classes.
> Logger/analyzer utilities can be used if the internal states are
> really necessary.
>
> Or, I missed something important for testing?

See my reply to Andrei Polushin earlier in this thread for an
argument -- I'm not saying or suggesting that you're mistaken;
simply that in that post, I gave some arguments in favor of
testing more than just the public interfaces.

Carlos
--

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Andrei Polushin on
Dave Steffen wrote:
> Alas, "#define private public" is evil, but it's the only idea I've
> come up with, or heard from anybody else, that allows unit tests
> access to class' innards, with _no_ change to class design or
> implementation.

For legacy code, it could be useful to inject several calls to logger
object at some control points of that code, then examine the results
gathered by logger in your test.

Such technique requires no changes in design, no hacking, and isolates
tester from implementation details.

--
Andrei Polushin


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]