如何让google-test类与我的班级成为朋友?

paj*_*ton 35 c++ friend googletest

我听说有可能让google-test TestCase类朋友加入我的课程,从而使测试能够访问我的私人/受保护成员.

怎么做到这一点?

hob*_*bit 37

试试这个(直接来自Google Test docs ...):

FRIEND_TEST(TestCaseName, TestName);
Run Code Online (Sandbox Code Playgroud)

例如:

// 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().
}
Run Code Online (Sandbox Code Playgroud)

  • 我怎么能以一种不强迫我在类文件`Foo`的头文件中包含googletest头文件的方式来做到这一点? (26认同)
  • 是.每项测试在技术上都是一个类,你需要一次与他们成为一个朋友. (2认同)
  • 请注意,test 和待测类必须位于相同的命名空间中,如 [googletest `gtest_prod.h`](https://github.com/google/googletest/blob/3306848f697568aacf4bcca330f6bdd5ce671899/googletest/include/gtest/ gtest_prod.h#L55) (2认同)

Ral*_*zle 25

我知道这已经过时了,但今天我正在寻找相同的答案."gtest_prod.h"只是介绍了一个简单的宏来引用测试类.

#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test
Run Code Online (Sandbox Code Playgroud)

所以FRIEND_TEST(FooTest, BarReturnsZeroOnNull);相当于:

friend class FooTest_BarReturnsZeroOnNull_Test;
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为每个测试都是它自己的类,如上一个答案所述.


Cor*_*tor 8

当您的测试类和测试类位于不同的命名空间中时(例如您的测试位于全局命名空间中),您可能需要前向声明您的测试类并在以下位置添加命名空间前缀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().
}
Run Code Online (Sandbox Code Playgroud)

我知道朋友单元测试(或一般 C++ 中的友好性)和白盒测试是一个有争议的主题,但是当您研究复杂的科学算法时,您需要测试和验证其中的每一步,但您不这样做由于不想公开(甚至受保护)接口,友元测试在我看来是一种简单而实用的解决方案,特别是在测试驱动的开发方法中。如果使用友好性或白盒测试违背了自己的宗教信仰,那么以后总是可以重构代码(或完全删除白盒测试)。


Mar*_*n G 5

更好的策略是不允许在单元测试中进行朋友测试。

允许朋友测试访问私有成员将导致难以维护的代码库。重构组件的内部实现详细信息时中断的测试不是您想要的。如果要花更多精力在可以通过组件的公共接口测试组件的设计上,您将获得仅在组件的公共接口更新时才需要更新的测试。

依赖测试的情况gtest/gtest_prod.h应视为设计不良的标志。

  • 我认为这非常依赖于应用程序,在某些情况下我可以理解你的观点。然而,如果您考虑 HPC/科学计算应用程序,这并不是设计不佳的迹象。在许多情况下,求解器的接口非常简单 - .solve(),但依赖于复杂的数学和控制方程的求解。这些方程将被分解为更小的私有函数,您肯定想要对其进行单元测试。 (4认同)
  • 在制定测试策略时,需要在各个方面进行权衡。您指出的优点是有效的,但这并不意味着使用“friend”进行测试总是一个坏主意。 (3认同)
  • 我知道这是有争议的(希望它为您赢得了“有争议的答案”徽章&lt;grin&gt;),但是我很高兴有人提出了这个观点。许多人都对此表示赞同。https://dzone.com/articles/principles-creating (2认同)
  • 这在一般情况下是正确的,但对于 UI 测试(考虑 QT),您通常希望获得通常不会公开的子小部件。例如,我需要检查按下按钮时小部件是否可见。该小部件通常不会公开公开。 (2认同)