Re: [googletest] Unable to test private methods

1,313 views
Skip to first unread message

Keith Ray

unread,
Nov 1, 2012, 2:17:25 PM11/1/12
to Mihaela, googletes...@googlegroups.com
Make a "friend" helper class, or make the 'private' entity public. Either way, you have to modify the class under test slightly.

The test is trying to tell you that your design isn't testable.

On 2012 Nov 01, at 2:07 AM, Mihaela wrote:

I have tried every permutation I could find, from the Primer, Advanced Guide, FAQ, and some questions on the web, trying to test a private function.

The setup:
generic solution:
-- production code project
   -- fileA.h
     --class X:  constructors X, X(a,b,c), private Z
   -- fileA.cpp
-- test project: 
  --- file T.h: #include gtest.h, fileA.h
     -- namespace{
       .... all the tests
 }
I was unable to get any version suggested in the guide to work, every attempt resulted in denied access to function Z.
I have one suspicion, which I cannot test, the fact that calling FRIEND_TEST in fileA.h is useless, since fileA has no way to understand the names of classes in fileT.h - and the only way to fix this problem is to create circular references (include fileT.h in fileA.h).

The best results (maybe) were achieved with the suggestion of changing he private modifier to protected, and changing the access level of the method again through inheritance... 
The only problem is, I was unable to apply that method to the class constructors, without which the whole concept is useless.

Changing the solution structure, placing the test code inside the production code, is completely out of the question.

Please, could someone give me a suggestion on how to get tests to work ?

Martin Grund

unread,
Nov 1, 2012, 2:23:44 PM11/1/12
to Keith Ray, Mihaela, googletes...@googlegroups.com
Wouldn't this be a perfect case for PIMPL or Facade Implementations? The
implementation can be public, but the Facade hides private methods.

Mihaela

unread,
Nov 1, 2012, 2:39:11 PM11/1/12
to googletes...@googlegroups.com, Mihaela
Making 'private' functions 'public' means major changes in code. There are reasons, sometimes, to have helper functions stay private.

I have read endless debates on whether to unit-test private functions, or only test them through their public interface...
Testing them through the interface though is no longer 'unit testing', it becomes integration testing.
If there have to be changes in the implementation of a helper function, those changes must be tested !

So... Back to the original problem.

I have added a 
friend class classname_methodname_Test 
to the tested class. Nothing happened, still method to be tested is inaccessible. Well, there is the issue of the two projects living in different namespaces.

I wrote the word "extern" in front, and removed the "namespace" from the test class.
Now I am faced with link errors: The TestInfo class seems to be redefined...

A different approach that I have tried:

Change the modifier for the 'private' to 'protected', to keep at least the idea... Add a wrapper class to the test class, redefining the protected method to public.
Error:
"All tests in the same test case must have the same class. class.  However, in test case xxxxxx, 
you defined test zzzzz and test zzzzz using two different test fixture classes.  This can happen if
the two classes are from different namespaces or translation units and have the same name.  
You should probably rename one of the classes to put the tests into different test cases."

There is only one test fixture class - but then, there is also the wrapper class... so At this point, nothing seems to work.

What is "PIMPL or Facade Implementations" ? 

Martin Grund

unread,
Nov 1, 2012, 2:49:19 PM11/1/12
to Mihaela, googletes...@googlegroups.com
With a Facade [1,2] you can basically structure your code into multiple
parts that can be than hidden behind a "facade". Since the facade
defines the API to the consumer it provides the required visibility
properties. Since the parts defining the facades are internal only they
can make methods public that otherwise would be not accessible.

Basically what you could do is

--A
--private:
--doSomething()
---AImpl.doSomething()

AImpl
--public:
--doSomething():
----implementation goes here

What you would achieve is a) simpler component structures and b) decoupling.

The PIMPL idiom allows you to reduce compile time by decoupling the
interface of A from the implementation of AImpl using pointers [3,4]

Hope this helps,

Martin


[1] http://en.wikipedia.org/wiki/Facade_pattern
[2] http://en.wikipedia.org/wiki/Delegation_pattern
[3] http://www.gotw.ca/gotw/024.htm
[4] http://www.gotw.ca/publications/mill04.htm

Keith Ray

unread,
Nov 1, 2012, 3:01:33 PM11/1/12
to Mihaela, googletes...@googlegroups.com

davitr

unread,
Nov 1, 2012, 9:08:34 PM11/1/12
to gunit...@google.com, googletes...@googlegroups.com, mihaela...@urbanrobotics.net
Have you tried to put class X and tests in the same namespace ?

Mihaela

unread,
Nov 6, 2012, 11:48:34 AM11/6/12
to googletes...@googlegroups.com
Eliminating the namespace on the tests was necessary (since I could not add namespaces to the existing, complex and large production code).

My major mistake though: I didn't realize that tests had to be in the cc file, otherwise they create duplicate code...

Thank you for your answers.
Reply all
Reply to author
Forward
0 new messages