如何使 google-test 课程与我的课程成为朋友?

发布于 2024-08-24 08:07:40 字数 83 浏览 9 评论 0原文

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

如何做到这一点?

I heard there is a possibility to enable google-test TestCase classes friends to my classes, thus enabling tests to access my private/protected members.

How to accomplish that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

三五鸿雁 2024-08-31 08:07:40

试试这个(直接来自谷歌测试文档...):

FRIEND_TEST(TestCaseName, TestName);

例如:

// 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().
}

Try this (straight from Google Test docs...):

FRIEND_TEST(TestCaseName, TestName);

For example:

// 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().
}
蝶…霜飞 2024-08-31 08:07:40

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

#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test

因此 FRIEND_TEST(FooTest, BarReturnsZeroOnNull); 相当于:

friend class FooTest_BarReturnsZeroOnNull_Test;

这有效,因为每个测试都是其自己的类,如前面的答案中所述。

I know this is old but I was searching for the same answer today. "gtest_prod.h" just introduces a simple macro to reference test classes.

#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test

So FRIEND_TEST(FooTest, BarReturnsZeroOnNull); is equivalent to:

friend class FooTest_BarReturnsZeroOnNull_Test;

This works because each test is its own class as mentioned in the previous answer.

温柔戏命师 2024-08-31 08:07:40

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

允许友元测试访问私有成员将导致代码库难以维护。每当重构组件的内部实现细节时就会中断的测试不是您想要的。如果付出额外的努力来获得可以通过其公共接口测试组件的设计,那么您将获得只需要在组件的公共接口更新时更新的测试。

依赖 gtest/gtest_prod.h 的测试应该被视为设计不佳的标志。

A far better strategy is to not allow friend tests among your unit tests.

Allowing friend tests accessing private members will lead to a code base that is hard to maintain. Tests that break whenever a component's inner implementation details are refactored is not what you want. If extra effort is instead put into getting a design where components can be tested through their public interface, you will get tests that only need updating whenever the public interface of a component is updated.

Tests relying on gtest/gtest_prod.h should be seen as a sign of poor design.

国产ˉ祖宗 2024-08-31 08:07:40

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

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

When your tested class and your test class are in a different namespace (e.g. your tests are in the global namespace), you may need to forward-declare your test class and add your namespace prefix in 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().
}

I know that friend unit tests (or the friendliness in C++ in general) and white-box testing are a controversial subject, but when you work on complex, scientific algorithms, each step of which you need to test and validate, but that you don't want to expose in public (or even protected) interfaces, friend tests appear to me as a simple and pragmatic solution, especially in a test-driven development approach. It is always possible to refactor the code later (or to completely remove white-box tests) if it's against one's religion to use the friendliness or white-box testing.

聽兲甴掵 2024-08-31 08:07:40

如果您不想使用 FRIEND_TEST 单独列出每个测试用例,另一种选择是定义一个测试夹具类,然后对其进行友元化:

class Foo
{
    ...
private:
    friend class FooTest;
};
...
class FooTest : public ::testing::Test
{
protected:
    int AccessPrivateFooThing(Foo& foo) { ... }    
    ...
};
...
TEST_F(FooTest, PrivateThing)
{
   ...
   int result = AccessPrivateFooThing(foo);
   ...
}

但是,需要注意的是, 测试装置本身定义的方法将有权访问 Foo 的私有成员;测试本身不会。您必须在需要访问的固定装置中定义访问器、保镖或其他辅助方法。与其他一些解决方案相比,这需要更多的样板文件,但也更明确,这有望阻止过多地触及内部。

如果您遇到命名空间问题,只需确保测试装置与相关类位于同一命名空间即可;无论如何,这是一个很好的做法。

仍然强烈鼓励在合理可行的情况下仅测试公共成员,尽管我确实同意有时这样做更有意义。

If you don't want to have to individually list each test case with FRIEND_TEST, another option is to define a test fixture class and then friend that instead:

class Foo
{
    ...
private:
    friend class FooTest;
};
...
class FooTest : public ::testing::Test
{
protected:
    int AccessPrivateFooThing(Foo& foo) { ... }    
    ...
};
...
TEST_F(FooTest, PrivateThing)
{
   ...
   int result = AccessPrivateFooThing(foo);
   ...
}

However a caveat with this is that only methods defined in the test fixture itself will have access to Foo's private members; the tests themselves will not. You'll have to define accessors, bouncers, or other helper methods within the fixture where that access is required. This requires a bit more boilerplate than some other solutions, but is also more explicit, which hopefully discourages too much reaching into internals.

If you encounter issues with namespaces, simply ensure that the test fixture is in the same namespace as the class in question; this is a good practice anyway.

It's still strongly encouraged to test only public members where reasonably feasible, though I do agree that there are some times where this makes more sense.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文