Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Google’s gtest Not Handling Friend Tests Correctly

0.00/5 (No votes)
29 Oct 2012CPOL 11.1K  
You can’t properly friend test methods that are in a different namespace than the class being tested.

I was using Google’s gtest unit test framework today and I found an annoying problem – you can’t properly friend test methods that are in a different namespace than the class being tested.

Here is a typical situation:

C++
namespace MyNamespace
{
   class MyClass
   {
      public:
         MyClass(int inData): data(inData){}
      private:
         int data;
   };
}//end namespace

namespace MyNamespace
{
namespace TEST
{
   class MyTestClassFixture
   {
      static const int fixtureData;
   }
   static const MyTestClassFixture::fixtureData = 5;

   TEST_F(MyTestClassFixture, TestEqual)
   {
      MyClass testClass(5);
      ASSERT_EQ(fixtureData, testClass.data);
   }
}
}

Since the unit test needs to access the private data of the class, it would seem logical to make it a friend class. The framework provides a macro that does that – FRIEND_TEST, so you might be tempted to do something like this:

C++
namespace MyNamespace
{
//Forward declare the tests
namespace TEST
{
   TEST_F(MyTestClassFixture, TestEqual)
}
   class MyClass
   {
      public:
         MyClass(int inData): data(inData){}
         FRIEND_TEST(MyTestClassFixture, TestEqual)
      private:
         int data;
   };
}//end namespace

Neither of those works. FRIEND_TEST macro extends to friend class MyTestClassFixture_TestEqual_Test, which obviously does not include the namespace of the test class. TEST_F also expands to something that’s not of any use.

The only way I could think of to go around this very annoying problem, was to roll my own macros – one to get the name of the class, and another to do the forward declaration:

C++
namespace MyNamespace
{
//Forward declare the tests
namespace TEST
{
   #define GET_CLASS_NAME(test_case_name, test_name)\
   test_case_name##_##test_name##_Test

   #define GET_DECORATED_CLASS_NAME(namespace, test_case_name, test_name)\
   namespace::GET_CLASS_NAME(test_case_name, test_name)

   class GET_CLASS_NAME(MyTestClassFixture, TestEqual);
}
   class MyClass
   {
      public:
         MyClass(int inData): data(inData){}
         friend class GET_DECORATED_CLASS_NAME(TEST, MyTestClassFixture, TestEqual);
      private:
         int data;
   };
}//end namespace

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)