Search code examples
c++unit-testinggoogletest

What are the possible ways to test private methods with a parameterised unit test with Google test API for C++?


I'm using Google Test api to unit test C++ code.

with google test API sample, i see there is a option to test the private methods with FRIEND_TEST macro. Also i see TEST_P,INSTANTIATE_TEST_CASE_P macros for parameterized tests.

So i tried below logic to implement parameterised unit test for private method. But i got an error with 'Foo::Bar' : cannot access private member declared in class 'Foo'. when i try to use the class FRIEND_TEST_Test3 to test with parameterized test macro TEST_P.

So please let me know the possible ways to test private method with parameterised unit test with Google test macros.

class Foo {
public:
  Foo() {}

private:
  int Bar() const { return 1; }

FRIEND_TEST(FRIEND_TEST_Test, TEST);
FRIEND_TEST(FRIEND_TEST_Test2, TEST_F);
FRIEND_TEST(FRIEND_TEST_Test3, TEST_P);
};

TEST(FRIEND_TEST_Test, TEST) {
  ASSERT_EQ(1, Foo().Bar());
}

class FRIEND_TEST_Test2 : public ::testing::Test {
public:
  Foo foo;
};

TEST_F(FRIEND_TEST_Test2, TEST_F) {
  ASSERT_EQ(1, foo.Bar());
}

class CodeLocationForTESTP : public ::testing::TestWithParam<int> {
};

INSTANTIATE_TEST_CASE_P(, CodeLocationForTESTP, ::testing::Values(0,1,2,1,0));

TEST_P(CodeLocationForTESTP, Verify) {
    ASSERT_TRUE(0==GetParam());
}


class FRIEND_TEST_Test3 : public ::testing::Test,public ::testing::TestWithParam<int> {
public:
  Foo foo;
};

INSTANTIATE_TEST_CASE_P(, FRIEND_TEST_Test3, ::testing::Values(0,1,2,1,0));

TEST_P(FRIEND_TEST_Test3, Verify) {
    ASSERT_EQ(1, foo.Bar());
}

Solution

  • As stated in the googletest document, the second argument of FRIEND_TEST must be the test name which we want to execute. Since your 3rd unit test is TEST_P(FRIEND_TEST_Test3, Verify) and its test name is Verify, not TEST_P, you have to define FRIEND_TEST(FRIEND_TEST_Test3, Verify) in the private scope of Foo.

    In addition, since ::testing::Test is a base class of ::testing::TestWithParam, we don't need to explicitly inherit ::testing::Test to FRIEND_TEST_Test3.

    Thus the following code would well work for you:

    #include <gtest/gtest.h>
    #include <gtest/gtest_prod.h>
    
    class Foo
    {
    public:
        Foo() {}
    
    private:
        int Bar() const { return 1; }
    
        FRIEND_TEST(FRIEND_TEST_Test3, Verify);
                                    // ^^^^^^ not TEST_P
    };
    
    class FRIEND_TEST_Test3 : public ::testing::TestWithParam<int>
    {
    public:
        Foo foo;
    };
    
    INSTANTIATE_TEST_CASE_P(, FRIEND_TEST_Test3, ::testing::Values(0,1,2,1,0));
    
    TEST_P(FRIEND_TEST_Test3, Verify)
    {
        ASSERT_EQ(1, foo.Bar());
    }