#ifdef GTEST
#define private public
#define protected public
#endif
It becomes too easy for test code to delve into the private parts of
classes, and thus become fragile... when the class internals change,
the test code has to change as well.
If you refactor, moving code from test into production code, you or
your teammates may be surprised that the code no longer compiles in
production.
If the private parts of a class are interesting enough to test, they
probably belong to another class, where they are public, and tested
there. Search the web for the code smell description "Iceberg Class".
I've been in this situation: I spent half an hour trying to find out
why some test code was able to access private methods of a C++ class.
I had declared a method private so that I could find all the external
callers of that method [this is a "lean-on-the-compiler" step for
manually refactoring code -- make something illegal and then change
those pieces of code that no longer compile.] I eventuallty found
"#define private public" and removed it.
The more courteous thing would be define a macro like so:
#define TESTABLE_PRIVATE public
Courteous programmers don't redefine keywords of the language you are using.
--
C. Keith Ray, IXP Coach, Industrial Logic, Inc.
http://industriallogic.com 866-540-8336 (toll free)
Groove with our Agile Greatest Hits: http://www.industriallogic.com/elearning/
http://agilesolutionspace.blogspot.com/
2010/6/28 Dbger <baiya...@gmail.com>:
class TestClass : public ClassWithPrivateMembers
{
public:
memberYouWantPublic;
// parent class has protected: memberYouWantPublic
};
--
C. Keith Ray
Web: http://industriallogic.com
Twitter: @CKeithRay, @IndustrialLogic
Amplify Your Agility
Coaching | Training | Assessment | eLearning
I think you mean
using memberYouWantPublic;
> // parent class has protected: memberYouWantPublic
> };
>
> --
> C. Keith Ray
> Web: http://industriallogic.com
> Twitter: @CKeithRay, @IndustrialLogic
>
> Amplify Your Agility
> Coaching | Training | Assessment | eLearning
> On Tue, Jun 29, 2010 at 2:43 AM, Novaisas <nova...@gmail.com> wrote:
>>
>> I use the trick below:
>>
>> TEST_F(SomeTest, Specific)
>> {
>> ClassWithPrivateMembers* pC;
>>
>> class TestClass : public ClassWithPrivateMembers
>> {
>> friend class SomeTest_Specific_Test;
>> };
>>
>> TestClass* pTC = reinterpret_cast<TestClass*> (pC);
>>
>> // here you have access to the private members of pC by using pTC pointer
>> }
>>
>>
>
--
Zhanyong
Uh, please don't refer to the name SomeTest_Specific_Test directly.
That's gtest's implementation detail and may change at any time
without notice, which is why we have FRIEND_TEST.
> };
>
> TestClass* pTC = reinterpret_cast<TestClass*> (pC);
I think you mean static_cast here. reinterpret_cast is for a different purpose.
>
> // here you have access to the private members of pC by using pTC
> pointer
I think you'll have access to the protected members, but not the private ones.
> }
>
>
>
--
Zhanyong
On Mon, Jun 28, 2010 at 2:52 AM, Dbger <baiya...@gmail.com> wrote:
> Hi, All
> In GTest's official document, there is a link suggests how to test class's
> private member. However, I think FRIEND_TEST is way from convenient and come
> up with an new idea, it is simple, but works:
>>
>> #ifdef GTEST
>>
>> #define private public
This is invalid C++. According to C++98 standard:
17.4.3.11 Macro names [lib.macro.names]
"Nor shall ... define macros for names lexically identical to keywords."
In other words, you are not allowed to #define a C++ keyword. While
your current compiler may not mind, the code is not portable, and may
break with the next version of the compiler.
>> #define protected public
>>
>> #endif
>
> By forcing all the class members to public in testing code we are able to
> access anything we want(details please see this blog entry, Chinese). And I
> thought it only change the access level of the members and should have no
> impact on the class's behavior. Do you see any potential risk in this
> approach?
In addition to the #define isn't allowed, changing the access
specifiers can affect the lay-out of the non-static member variables:
9.2 Class members, paragraph 12:
"The order of allocation of nonstatic data members separated by an
access-specifier is unspecified."
In other words, the compiler is free to re-arrange the order of
different access specifier groups. For example, a compiler is allowed
to put all private data members before other data members, and your
trick will change the object lay-out, causing subtle problems when
your test code is linked with production code.
> Thanks.
>
> 技术博客:http://www.cnblogs.com/baiyanhuang/
> 我的豆瓣:http://www.douban.com/people/baiyanhuang/
>
--
Zhanyong
Don't even do this, as it may change the object lay-out.
>
> Courteous programmers don't redefine keywords of the language you are using.
>
> --
> C. Keith Ray, IXP Coach, Industrial Logic, Inc.
> http://industriallogic.com 866-540-8336 (toll free)
> Groove with our Agile Greatest Hits: http://www.industriallogic.com/elearning/
> http://agilesolutionspace.blogspot.com/
>
>
> 2010/6/28 Dbger <baiya...@gmail.com>:
>> Hi, All
>> In GTest's official document, there is a link suggests how to test class's
>> private member. However, I think FRIEND_TEST is way from convenient and come
>> up with an new idea, it is simple, but works:
>>>
>>> #ifdef GTEST
>>>
>>> #define private public
>>>
>>> #define protected public
>>>
>>> #endif
>>
>> By forcing all the class members to public in testing code we are able to
>> access anything we want(details please see this blog entry, Chinese). And I
>> thought it only change the access level of the members and should have no
>> impact on the class's behavior. Do you see any potential risk in this
>> approach?
>> Thanks.
>>
>> 技术博客:http://www.cnblogs.com/baiyanhuang/
>> 我的豆瓣:http://www.douban.com/people/baiyanhuang/
>>
>
--
Zhanyong
Uh, please don't refer to the name SomeTest_Specific_Test directly.
That's gtest's implementation detail and may change at any time
without notice, which is why we have FRIEND_TEST.
I think you mean static_cast here. reinterpret_cast is for a different purpose.
I think you'll have access to the protected members, but not the private ones.