【问题标题】:What are the possible ways to test private methods with a parameterised unit test with Google test API for C++?使用 Google test API for C++ 通过参数化单元测试来测试私有方法的可能方法是什么?
【发布时间】:2019-05-10 08:36:59
【问题描述】:

我正在使用 Google Test api 对 C++ 代码进行单元测试。

使用 google 测试 API 示例,我看到有一个选项可以使用 FRIEND_TEST 宏测试私有方法。我还看到了用于参数化测试的 TEST_P、INSTANTIATE_TEST_CASE_P 宏。

所以我尝试了以下逻辑来实现私有方法的参数化单元测试。但是我遇到了 'Foo::Bar' 错误:无法访问在类 'Foo' 中声明的私有成员。当我尝试使用类 FRIEND_TEST_Test3 使用参数化测试宏 TEST_P 进行测试时。

所以请告诉我使用 Google 测试宏通过参数化单元测试来测试私有方法的可能方法。

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());
}

【问题讨论】:

  • 我个人会质疑测试私有方法的价值。它们是“实施细节”。就其本质而言,客户端程序员不会使用它们,并且它们的“接口”比公共方法更频繁地更改。

标签: c++ unit-testing googletest


【解决方案1】:

the googletest document 中所述,FRIEND_TEST 的第二个参数必须是我们要执行的测试名称。 由于您的第三个单元测试是TEST_P(FRIEND_TEST_Test3, Verify),并且它的测试名称是Verify,而不是TEST_P,因此您必须在Foo 的私有范围内定义FRIEND_TEST(FRIEND_TEST_Test3, Verify)

另外,由于::testing::Test::testing::TestWithParam的基类,我们不需要将::testing::Test显式继承到FRIEND_TEST_Test3

因此,以下代码很适合您:

#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());
}

【讨论】:

    【解决方案2】:

    将您的测试移动到自己的文件中(例如test.cpp)。这个文件只允许包含测试一个没有生产性的代码。现在将 #define private public 添加到 - 现在您可以访问私有成员,而无需在测试中引入奇怪的 getter、朋友或其他任何东西。

    C++ 标准说这会导致未定义的行为 (Define private to public in C++),但它从来没有给我带来任何问题。

    我认为修改我们的代码以使其可测试不是一个好习惯

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-10
      • 1970-01-01
      • 1970-01-01
      • 2018-01-15
      • 2012-05-02
      相关资源
      最近更新 更多