[Boost-users] [test] testing protected/private methods out of test suits

603 views
Skip to first unread message

M. Siebeneicher

unread,
Sep 18, 2008, 3:26:44 AM9/18/08
to boost...@lists.boost.org
Hello boost-users,

I tried to test protected/private class methods by declaring the test-case-class as a friend of the class-to-test. The test-case-class is defined by the macro BOOST_FIXTURE_TEST_CASE(T, F). That works fine as long as I encapsulate the test-case with BOOST_AUTO_TEST_SUITE(suite_name) and BOOST_AUTO_TEST_SUITE_END().

I'm not able to define the correct friend declaration, cause the compiler . Can someone give me hint, please?

the code looks like this:

// test-case-class.cpp
namespace foo { namespace bar {

BOOST_AUTO_TEST_SUITE(suite_name)

struct F {
class-to-test class_to_test_instance;
}
.
.
.

BOOST_FIXTURE_TEST_CASE(test-case-class, F) {
F.class_to_test_instance.i;
.
.
.
}
.
.
.
BOOST_AUTO_TEST_SUITE_END()
}}

class-to-test.cpp

namespace foo { namespace bar {
.
.
.
class class-to-test {
public:
friend struct test-case-class; // that's wrong // No access to protected member i
friend struct suite_name::test-case-class; // this is wrong, too: compiler error, can't find foo::bar::suite_name, ....

protected:
int i;
.
.
.
};

}}

greetz,
modbom

--
GMX startet ShortView.de. Hier findest Du Leute mit Deinen Interessen!
Jetzt dabei sein: http://www.shortview.de/wasistshortview.php?mc=sv_ext_mf@gmx
_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

Robert Mecklenburg

unread,
Sep 18, 2008, 11:16:27 AM9/18/08
to boost...@lists.boost.org
M. Siebeneicher writes:
> I tried to test protected/private class methods by declaring the
> test-case-class as a friend of the class-to-test.

Here's what we do to unit test our classes:

#define private public
#define protected public
#include <common/Blob.hpp>

This makes our unit testing much easier! ;-)

Cheers,
--
Robert

M. Siebeneicher

unread,
Sep 19, 2008, 2:34:28 AM9/19/08
to boost...@lists.boost.org
> M. Siebeneicher writes:
> > I tried to test protected/private class methods by declaring the
> > test-case-class as a friend of the class-to-test.
>
> Here's what we do to unit test our classes:
>
> #define private public
> #define protected public
> #include <common/Blob.hpp>
>
> This makes our unit testing much easier! ;-)
>
> Cheers,
>
> --
> Robert

I did this before but now it doesn't work 'cause the class_to_test lies in another library than the test_case_class.

greetz,
Manuel
--
Ist Ihr Browser Vista-kompatibel? Jetzt die neuesten
Browser-Versionen downloaden: http://www.gmx.net/de/go/browser

Robert Mecklenburg

unread,
Sep 19, 2008, 12:22:05 PM9/19/08
to boost...@lists.boost.org
M. Siebeneicher writes:
> > #define private public
> > #define protected public
>
> I did this before but now it doesn't work 'cause the class_to_test
> lies in another library than the test_case_class.

I'm not sure I understand the problem. This hack works regardless of
the library decomposition. Visibility is purely a source-code
concern, just include #defines and the header declaring the class and
you can access anything even if it is in a different library.

Cheers,
--
Robert

Othman, Ossama

unread,
Sep 19, 2008, 1:08:06 PM9/19/08
to boost...@lists.boost.org
Hi,

>I'm not sure I understand the problem. This hack works regardless of
>the library decomposition. Visibility is purely a source-code
>concern, just include #defines and the header declaring the class and
>you can access anything even if it is in a different library.

I don't believe this is true for all compilers or in all cases. For example, changing the member visibility in a class I worked on broke binary compatibility in a library I built with MSVC++ 8. Similar complications may arise when using symbol hiding techniques, such as compiler-specific symbol visibility support, link scripts, etc.

HTH,
-Ossama
--
Disclaimer: The opinions expressed in this e-mail are my own, an in no way represent Intel opinions.

tras...@gmx.net

unread,
Sep 19, 2008, 3:37:01 PM9/19/08
to boost...@lists.boost.org

>Hi,

>

>>I'm not sure I understand the problem.  This hack works regardless of

>>the library decomposition.  Visibility is purely a source-code

>>concern, just include #defines and the header declaring the class and

>>you can access anything even if it is in a different library.

>

>I don't believe this is true for all compilers or in all cases.  For example, >changing the member visibility in a class I worked on broke binary >compatibility in a library I built with MSVC++ 8.  Similar complications may >arise when using symbol hiding techniques, such as compiler-specific symbol >visibility support, link scripts, etc

I've exactly that problem with MSVC++7.x. Compiling the class_to_test in the library with protected methods and trying to access this methods out from the test_case_class by including the header and #define protected public, gives me a "symbol not found compiler error". :-/

Juergen Hunold

unread,
Sep 21, 2008, 4:23:58 AM9/21/08
to boost...@lists.boost.org
Hi !

On Friday 19 September 2008 21:37:01 tras...@gmx.net wrote:

> I've exactly that problem with MSVC++7.x. Compiling the class_to_test in
> the library with protected methods and trying to access this methods out
> from the test_case_class by including the header and #define protected
> public, gives me a "symbol not found compiler error". :-/

Yes, that trick will not work with msvc because the access specifiers (public,
protected, private) get into the mangled name in the lib. So you are out of
luck here ;-((

Yours,

Jürgen
--
* Dipl.-Math. Jürgen Hunold ! Ingenieurgesellschaft für
* voice: ++49 511 262926 57 ! Verkehrs- und Eisenbahnwesen mbH
* fax : ++49 511 262926 99 ! Lister Straße 15
* juergen...@ivembh.de ! www.ivembh.de
*
* Geschäftsführer: ! Sitz des Unternehmens: Hannover
* Prof. Dr.-Ing. Thomas Siefer ! Amtsgericht Hannover, HRB 56965
* PD Dr.-Ing. Alfons Radtke !

Patrick Loney

unread,
Sep 22, 2008, 4:05:39 AM9/22/08
to boost...@lists.boost.org
> I tried to test protected/private class methods by declaring the
test->case-class as a friend of the class-to-test.

Why are you trying to do this? In test driven development you should be
testing the interfaces not the internals, from Wikipedia:

"Some may object that using strict black box testing does not provide
access to private data and methods. This is intentional; as the software
evolves, you may find the implementation of a class changes
fundamentally. Remember a critical step of test-driven development is to
refactor. Refactoring may introduce changes which adds or removes
private members, or alters an existing member's type. These changes
ought not break existing tests. Unit tests that exploit glass box
testing are highly coupled to the production software; changing the
implementation of a class or module may mean you must also update or
discard existing tests, things which should never have to occur. For
this reason, glass box testing must be kept to the minimum possible.
White box testing should never be used in test-driven development."

Your private and protected methods should all be tested via calls to the
public methods.

******************************************************************************

"This message and any attachments are solely for the intended recipient and may contain confidential and privileged information. If you are not the intended recipient, any disclosure, copying, use, or distribution of the information included in this message and any attachments is prohibited. If you have received this communication in error, please notify us by reply e-mail and immediately and permanently delete this message and any attachments. Thank you."

Interactive Transaction Solutions Ltd (2473364 England)

Registered Office:
Systems House,
Station Approach
Emsworth PO10 7PW

**********************************************************************

Ce message électronique contient des informations confidentielles à l'usage unique des destinataires indiqués, personnes physiques ou morales. Si vous n'êtes pas le destinataire voulu, toute divulgation, copie, ou diffusion ou toute autre utilisation de ces informations, est interdite. Si vous avez reçu ce message électronique par erreur, nous vous remercions d'en avertir son expéditeur immédiatement par email et de détruire ce message ainsi que les éléments attachés.

Interactive transaction Solutions SAS- France (RCS Pontoise : 489 397 877)

Siège social :
Parc Saint Christophe,
10, Avenue de l’Entreprise
95865 Cergy-Pontoise Cedex

______________________________________________________________________
This email has been scanned by the MessageLabs Email Security System.
For more information please visit http://www.messagelabs.com/email
______________________________________________________________________

Patrick Loney

unread,
Sep 22, 2008, 4:58:30 AM9/22/08
to boost...@lists.boost.org

>> I tried to test protected/private class methods by declaring the

test->>case-class as a friend of the class-to-test.

> Why are you trying to do this? In test driven development you should
be >testing the interfaces not the internals, from Wikipedia:

Apologies, you 'should', of course, be doing whatever you think best,
however is it not possible to test your private methods via the public
interface?

Jonathan Franklin

unread,
Sep 22, 2008, 1:32:23 PM9/22/08
to boost...@lists.boost.org
On Sun, Sep 21, 2008 at 2:23 AM, Juergen Hunold <juergen...@ivembh.de> wrote:
On Friday 19 September 2008 21:37:01 tras...@gmx.net wrote:

> I've exactly that problem with MSVC++7.x. Compiling the class_to_test in
> the library with protected methods and trying to access this methods out
> from the test_case_class by including the header and #define protected
> public, gives me a "symbol not found compiler error". :-/

Yes, that trick will not work with msvc because the access specifiers (public,
protected, private) get into the mangled name in the lib. So you are out of
luck here ;-((

The '#define private public' trick works for me using MSVS 2005 and static libraries.

Jon

tras...@gmx.net

unread,
Sep 22, 2008, 2:14:19 PM9/22/08
to boost...@lists.boost.org
Am Mo September 22 2008 10:58:30 schrieb Patrick Loney:
> >> I tried to test protected/private class methods by declaring the
>
> test->>case-class as a friend of the class-to-test.
>
> > Why are you trying to do this? In test driven development you should
>
> be >testing the interfaces not the internals, from Wikipedia:
>
> Apologies, you 'should', of course, be doing whatever you think best,
> however is it not possible to test your private methods via the public
> interface?

You mean by deriving my class_to_test with derived_class and wraping the
protected class_to_test::method_to_test by a public method in derived_class?

That's possible, but I didn't like that. Because if I'm precise I only test
the public method of derived_class that way ;-) But if nothing works, I will
do that.

To return to your previous posting:
I try to do my best and test only public method. But sometimes it's very hard,
especially for complex protected methods. Either you use the way descripted
above or you move the method to a helper class. Both alternatives are not
elegant I think.

greetz
Manuel
>
> ***************************************************************************

Steven Watanabe

unread,
Sep 22, 2008, 2:33:03 PM9/22/08
to boost...@lists.boost.org
AMDG

tras...@gmx.net wrote:
> To return to your previous posting:
> I try to do my best and test only public method. But sometimes it's very hard,
> especially for complex protected methods. Either you use the way descripted
> above or you move the method to a helper class. Both alternatives are not
> elegant I think.
>

I suppose that you could add

class C {
friend class C_test_access;
};

and define C_test_access in the tests, with
only static forwarding functions.

In Christ,
Steven Watanabe

Robert Mecklenburg

unread,
Sep 22, 2008, 2:44:01 PM9/22/08
to boost...@lists.boost.org
Jonathan Franklin writes:
> > On Friday 19 September 2008 21:37:01 tras...@gmx.net wrote:
> >
> > > I've exactly that problem with MSVC++7.x. Compiling the class_to_test in
> > > the library with protected methods and trying to access this methods out
> > > from the test_case_class by including the header and #define protected
> > > public, gives me a "symbol not found compiler error". :-/
> >
> > Yes, that trick will not work with msvc because the access
> > specifiers (public, protected, private) get into the mangled name
> > in the lib. So you are out of luck here ;-((
>
> The '#define private public' trick works for me using MSVS 2005 and static
> libraries.

I would swear that the standard indicated that public/private had no
effect on visibility, just accessibility. That is, changing a
symbol's access from private to public did not change the meaning of a
program. Stroustrup uses such language in the D&E of C++.

Obviously, Microsoft thinks differently.

Cheers,
--
Robert

Steven Watanabe

unread,
Sep 22, 2008, 2:53:35 PM9/22/08
to boost...@lists.boost.org
AMDG

Robert Mecklenburg wrote:
> I would swear that the standard indicated that public/private had no
> effect on visibility, just accessibility. That is, changing a
> symbol's access from private to public did not change the meaning of a
> program. Stroustrup uses such language in the D&E of C++.
>

If it is public in some places and private in others, it
violates the one definition rule and all bets are off.

In Christ,
Steven Watanabe

Zeljko Vrba

unread,
Sep 22, 2008, 3:18:30 PM9/22/08
to boost...@lists.boost.org
On Mon, Sep 22, 2008 at 12:44:01PM -0600, Robert Mecklenburg wrote:
>
> I would swear that the standard indicated that public/private had no
> effect on visibility, just accessibility. That is, changing a
> symbol's access from private to public did not change the meaning of a
> program. Stroustrup uses such language in the D&E of C++.
>
I recall somewhat vaguely a similar discussion on comp.lang.c++.moderated
where the conclusion was that redefining keywords such as public/private
via preprocessor macros leads to undefined behavior. I don't think that
MS violates the standard with this particular behavior.

Daniel Krügler

unread,
Sep 23, 2008, 1:41:54 AM9/23/08
to boost...@lists.boost.org
Zeljko Vrba wrote:
> On Mon, Sep 22, 2008 at 12:44:01PM -0600, Robert Mecklenburg wrote:
>> I would swear that the standard indicated that public/private had no
>> effect on visibility, just accessibility. That is, changing a
>> symbol's access from private to public did not change the meaning of a
>> program. Stroustrup uses such language in the D&E of C++.
>>
> I recall somewhat vaguely a similar discussion on comp.lang.c++.moderated
> where the conclusion was that redefining keywords such as public/private
> via preprocessor macros leads to undefined behavior. I don't think that
> MS violates the standard with this particular behavior.

Correct. This is worded in C++03, [lib.macro.names]/2:

"[..] Nor shall such a translation unit define macros for names
lexically identical to keywords."

The current working paper has refined this in [macro.names]/2:

"A translation unit shall not #define or #undef names lexically
identical to keywords."

Greetings from Bremen,

Daniel

Patrick Loney

unread,
Sep 23, 2008, 4:10:59 AM9/23/08
to boost...@lists.boost.org
>You mean by deriving my class_to_test with derived_class and wraping
the >protected class_to_test::method_to_test by a public method in
>derived_class?

No, I just meant testing the public members with all the parameters
required to fully test the private/protected methods as they are used by
your class. If someone writes a derived class that uses one of your
protected methods in a different way then they need to write test cases
to ensure that the method is producing the results they want. I don't
think your test cases can anticipate how your protected methods will be
used by derived classes.

On the other hand this is a bit simplistic but I think it would be
better than #defining protected to public?

Class classToTest
{
Public:
#ifdef UNIT_TESTING
testingAccessToMethodToTest() { methodToTest() ) }
#endif UNIT_TESTING
Protected:
methodToTest() {}
}

******************************************************************************

spiderlama

unread,
Sep 23, 2008, 7:41:21 PM9/23/08
to boost...@lists.boost.org
What about using a friend test fixture class to allow data access. See example below:

AClass.hpp:

namespace Test
{
    class AClass;
}

class AClass
{
    friend class Test::AClass;
    ...
};

Test/AClass.hpp:

#include "AClass.hpp"

namespace Test
{
    class AClass
    {
        // test cases referencing private ::AClass data
    };
}

But then derived classes will have to re-test the protected functions. Ideally there should be minimal protected functions.

Cheers,
spider.

Jonathan Franklin

unread,
Sep 23, 2008, 10:35:06 PM9/23/08
to boost...@lists.boost.org
On Mon, Sep 22, 2008 at 11:32 AM, Jonathan Franklin <franklin...@gmail.com> wrote:
The '#define private public' trick works for me using MSVS 2005 and static libraries.

Turns out that it only worked for me when building Debug.  The Release build generated undefined symbol errors at link-time.

Jon

Daryle Walker

unread,
Oct 27, 2008, 3:03:02 PM10/27/08
to boost...@lists.boost.org
[I'm just catching up on two months of unchecked e-mail.]

On Sep 18, 2008, at 3:26 AM, M. Siebeneicher wrote:

> I tried to test protected/private class methods by declaring the
> test-case-class as a friend of the class-to-test. The test-case-
> class is defined by the macro BOOST_FIXTURE_TEST_CASE(T, F). That
> works fine as long as I encapsulate the test-case with
> BOOST_AUTO_TEST_SUITE(suite_name) and BOOST_AUTO_TEST_SUITE_END().
>
> I'm not able to define the correct friend declaration, cause the
> compiler . Can someone give me hint, please?
>
> the code looks like this:

[TRUNCATE]

The previous responses took three approaches:

1. How to properly declare a friendly test apparatus.
2. How to (temporarily) mess with the definitions of "protected" and
"private" to make them publicly accessible, with various compiler-
dependent degrees of success.
3. Question on why you're doing this and come up with workarounds.

I'm going to go on track 3 myself. Protected and private methods
ultimately exist to support public ones. Therefore NO code should
exist in non-public methods that can't be activated through some
combination of public method calls (including friends). This
statement should definitely be followed for testing private methods.
Protected ones have a slight problem in that a derived class could
potentially use said methods with arbitrary sets of parameters that
none of the public methods can do (falling within pre-conditions, of
course). If your public methods cannot fully exercise some protected
ones, then you need to create a custom derived class for testing.
This is especially important if some private method code can only be
accessed when a protected method is called with unusual parameters.

For any method, no matter the accessibility level, make sure to do
additional testing with derived classes using overrides if a method
either is virtual or could call (directly or indirectly) a virtual
method.

--
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT hotmail DOT com

Reply all
Reply to author
Forward
0 new messages