Search code examples
c++namespacesfriendgoogletest

How to use friend class with namespace in gtest


Suppose my Add.h is within a namespace and I am making it a friend of AddTest so it can access AddTwoNumber.

namespace mynamespace
{

class Add
{
 friend class AddTest;

 public:
  Add(){};
  ~Add(){};

 private:
  int AddTwoNumber(const int a, const int b){return a+b};
};

}

And my AddTest.h is

#include "Add.h"
#include "gtest/gtest.h"

class AddTest : public ::testing::Test
{
 protected:
  AddTest(){};
  virtual ~AddTest(){};

  virtual void SetUp()
  {
    mynamespace::Add addobj;
    result = addobj.AddTwoNumber(2, 3);
  };

  virtual void TearDown(){};

  int result;
};

However, it is returning error that AddTwoNumber is private. The code works if I take out "mynamespace" in Add.h. Is there a way to keep the namespace yet still allow AddTest to access private methods in Add.h?


Solution

  • Test code should never appear in the declarations for production code. In other words, if AddTwoNumber needs to be tested, it's behavior should be testable and observable through the public members of the class Add. If noone can observe the consequences of AddTwoNumber from the callable interface of the class of Add, then how can it be doing anything useful?

    When you write code test-first, you end up with production code that follows this organization naturally. When you write the test after, you end up in a situation as you've described where the thing you want to test is buried inside. This is the situation with Legacy Code (code without tests). When you write the implementation before you write the test, you are creating legacy code.

    See Michael Feathers book "Working Effectively with Legacy Code" for more details on working with legacy code. He describes many techniques for decoupling code so that you can test it without unnecessarily polluting your public declarations.

    See my C++ Now! 2014 workshop on Test-Driven Development in C++ for a gentle introduction to test-driven development in C++ using Boost.Test. The workshop includes code for every step in the presentation so you can follow along directly on your computer with the presentation.

    Jeff Langr's book "Modern C++ Programming with Test-Driven Development" is an excellent treatment on test-driven development using modern C++. Jeff's book has a bibliography citing the research into empirical studies showing the benefits of test-driven development.