Boost logo

Boost Users :

From: Ed Johnson (ed_at_[hidden])
Date: 2006-05-02 22:04:10


Paul Giaccone wrote:
> Ryo IGARASHI wrote:
>
>> On 3/23/06, Leif Gruenwoldt <leifer_at_[hidden]> wrote:
>>
>>
>>> Is there a way to test the private functions of a class without moving
>>> them into public scope during test?
>>>
>>> What are some strategies for this?
>>>
>>>
>> Try following evil hack.
>>
>> // someclass_test.hpp
>> #define private public
>> #define protected public
>>
>> #include <someclass.hpp>
>>
>> #undef protected
>> #undef private
>>
>>
>
> Evil, evil, evil!
>
> Slightly less so is what I have done in my code. Define a variable (say,
> TESTING) in the makefile or preprocessor definitions of your test
> program. In your class definitin, change "private:" to the following:
>
> #ifdef TESTING
> public:
> #else
> private:
> #endif
>
> Of course, you leave TESTING undefined (or make sure it is undefined) in
> your non-test program.
>
> It's perhaps not nice to look at, but it's less nasty than the above
> hack, IMO.
>
> Paul

Hi Paul,

  I wanted to add to your post. I am trying to figure out a good
solution to Leif's problem for my own project. Your solution seemed
good, but I also want the ability to test just the public interface,
without simultaneous access to the private data. When I use the #ifdef
TESTING solution, my unit tests never test the classes as they will be
used by an end user because all class data is always public. This could
lead to a false sense of security from my unit tests.

So, here is my addition that I think is more comprehensive.

- Separate tests of protected and private members into their own suites.
- Surround these suites with:

#ifdef TEST_PRIVATE
        BOOST_AUTO_TEST_SUITE( A_Private );
                BOOST_AUTO_TEST_CASE( A_Test1_Private )
                {
                        A *p = new A();
                        BOOST_CHECK( p->privateData == 42 );
                }

                BOOST_AUTO_TEST_CASE( A_Test2_Private )
                {
                        A *p = new A();
                        BOOST_CHECK( p->privateFunction() == "foo" );
                }
        BOOST_AUTO_TEST_SUITE_END();
#endif //TEST_PRIVATE

By switching the TEST_PRIVATE definition on or off, I can test either
the pure public interface, or the private members temporarily exposed to
public.

I should probably also surround my public interface tests with:

#ifndef TEST_PRIVATE
        Public Tests...
#endif

So, that I never accidentally mix the two groups, which would lead to a
weakened set of tests on my public interface.

You could also extend this to Protected members as well.

#ifdef TEST_PROTECTED
                protected Tests...
#endif //TEST_PROTECTED

#ifndef TEST_PRIVATE || TEST_PROTECTED
        Public Tests...
#endif //TEST_PRIVATE || TEST_PROTECTED

You may want to keep protected tests separate from private tests as
well. (and vice versa)

#ifdef TEST_PROTECTED
        #ifndef TEST_PRIVATE
                
                protected Tests...

        #endif //!TEST_PRIVATE
#endif //TEST_PROTECTED

Any thoughts on this strategy?

One potential problem I see is that all private data in every class in
the testee app becomes public to each test at the same time. This
strategy doesn't let you access private data one class at a time in your
tests.

Thanks,

Ed


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net