58

I heard there is a possibility to enable google-test TestCase classes friends to my classes, thus enabling tests to access my private/protected members.

How to accomplish that?

pajton
  • 15,828
  • 8
  • 54
  • 65
  • Not an answer to this specific question, but a (controversial, to say the least) workaround for the same problem: one can always `#define private public` before including the definition of the class being tested. – jacquev6 Jul 21 '21 at 11:49
  • 1
    @jacquev6 the `#define private public` solution may not always be applicable as you may link against the actual unit (i.e. built without this re-#definition) possibly leading to missing linker symbols. In this case the `FRIEND_TEST` solution can help. All in all I would also recommend restricting the use of either solution to legacy code that can't / shouldn't be refactored. New code shall be directly designed for testability. – Roland Sarrazin Jan 20 '22 at 09:40

4 Answers4

58

Try this (straight from Google Test docs...):

FRIEND_TEST(TestCaseName, TestName);

For example:

// foo.h
#include <gtest/gtest_prod.h>

// Defines FRIEND_TEST.
class Foo {
  ...
 private:
  FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
  int Bar(void* x);
};

// foo_test.cc
...
TEST(FooTest, BarReturnsZeroOnNull) {
  Foo foo;
  EXPECT_EQ(0, foo.Bar(NULL));
  // Uses Foo's private member Bar().
}
hobbit
  • 631
  • 6
  • 3
  • 1
    What about if I have another test for instance BarReturnsOneOnSth. Do I have to add another FRIEND_TEST declaration for that test too? – pajton Mar 07 '10 at 13:41
  • 2
    Yes. Each test is technically a class, and you need to befriend them one at a time. – hobbit Mar 07 '10 at 13:48
  • 31
    How can I do it in a way which does not force me to include googletest header files in the header file with class `Foo`? – quant_dev Dec 12 '11 at 17:07
  • 1
    @quant_dev: Refer to Ralfizzle's answer for doing it without including it the gtest header. – Jatin Kumar Oct 07 '15 at 00:10
  • 2
    Note that test and to be tested class have to be in the same namespace, as explained in [googletest `gtest_prod.h`](https://github.com/google/googletest/blob/3306848f697568aacf4bcca330f6bdd5ce671899/googletest/include/gtest/gtest_prod.h#L55) – zeeMonkeez Oct 21 '18 at 21:40
  • 1
    [Here's the documentation for how to use `FRIEND_TEST()`](https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#testing-private-code), and [here's the definition for the `FRIEND_TEST` macro](https://github.com/google/googletest/blob/master/googletest/include/gtest/gtest_prod.h#L58). – Gabriel Staples Oct 01 '20 at 03:15
40

I know this is old but I was searching for the same answer today. "gtest_prod.h" just introduces a simple macro to reference test classes.

#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test

So FRIEND_TEST(FooTest, BarReturnsZeroOnNull); is equivalent to:

friend class FooTest_BarReturnsZeroOnNull_Test;

This works because each test is its own class as mentioned in the previous answer.

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
Ralfizzle
  • 477
  • 4
  • 10
10

A far better strategy is to not allow friend tests among your unit tests.

Allowing friend tests accessing private members will lead to a code base that is hard to maintain. Tests that break whenever a component's inner implementation details are refactored is not what you want. If extra effort is instead put into getting a design where components can be tested through their public interface, you will get tests that only need updating whenever the public interface of a component is updated.

Tests relying on gtest/gtest_prod.h should be seen as a sign of poor design.

Martin G
  • 17,357
  • 9
  • 82
  • 98
  • 4
    I understand that this is controversial (hopefully it earned you some kind of "controversial answer" badge ), but I am glad someone brought up this viewpoint. Many agree with @Martin on this! https://dzone.com/articles/principles-creating – pestophagous Jul 27 '17 at 23:15
  • 4
    This is true in general, but for UI testing (thinking of QT) you'll often want to get at child widgets that wouldn't normally be exposed. For example I need to check that when a button is pressed a widget becomes visible. The widget normally would not be exposed publicly. – CaptRespect Jun 12 '18 at 18:05
  • 7
    There are tradeoffs along various axes in developing testing strategies. The advantage you point to is valid, but that doesn't mean using `friend` for testing is always a bad idea. – Josh Burkart Oct 19 '20 at 21:58
  • 4
    I think this is very application dependent, in some cases I can see your point. If you, however, consider for example HPC/scientific computing applications this would not be a sign of poor design. In many cases, the interface to a solver is made very simple - .solve(), but relies on complicated mathematics and solving of governing equations. These equations will be broken into smaller private functions, which you would definitely want to unit test. – Bevan Jones Sep 02 '21 at 10:24
  • @BevanJones, that sounds like bad design to me. Anyways, of course we often have a system that has both good and bad sides to it. And often it's not reasonable to suggest that it should be re-written from scratch to make it more testable or whatever. That's reality, but it's still a sign of poor design choices. Not necessarily yours. – Martin G Sep 02 '21 at 10:45
  • @Martin G What would be considered better designs? Only potential options that immediately come to mind would be 1) exposing the private methods just for test (bad?), 2) keeping all the code in one big .solve() method (bad?), 3) moving the private functions to a helper class or some equivalent. Option 3 may be a better solution IFF the private helper functions are meaningful elsewhere which is not a guarantee. – R Schultz Sep 02 '22 at 15:42
9

When your tested class and your test class are in a different namespace (e.g. your tests are in the global namespace), you may need to forward-declare your test class and add your namespace prefix in FRIEND_TEST:

// foo.h
#include <gtest/gtest_prod.h>

// forward-declaration of test class
class FooTest_BarReturnsZeroOnNull_Test; 

// Defines FRIEND_TEST.
class my_namespace::Foo {
    ...
private:
    // Specify the global namespace (`::`) in the `FRIEND_TEST()` usage
    FRIEND_TEST(::FooTest, BarReturnsZeroOnNull);
    int Bar(void* x);
};

// forward-declaration of this namespace from foo_test.cc
using namespace my_namespace;

...
TEST(FooTest, BarReturnsZeroOnNull) {
    Foo foo;
    EXPECT_EQ(0, foo.Bar(NULL));
    // Uses Foo's private member Bar().
}

I know that friend unit tests (or the friendliness in C++ in general) and white-box testing are a controversial subject, but when you work on complex, scientific algorithms, each step of which you need to test and validate, but that you don't want to expose in public (or even protected) interfaces, friend tests appear to me as a simple and pragmatic solution, especially in a test-driven development approach. It is always possible to refactor the code later (or to completely remove white-box tests) if it's against one's religion to use the friendliness or white-box testing.

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
Corentor
  • 661
  • 1
  • 6
  • 11
  • 1
    This answer points one important thing other answers missed and save my world: the namespace matters quite a lot when using friend class. – Kir Chou May 06 '21 at 02:44