web-dev-qa-db-ja.com

google-testクラスを私のクラスと友達にする方法は?

私のクラスのgoogle-test TestCaseクラスのフレンドを有効にして、テストが私のプライベート/保護されたメンバーにアクセスできるようにする可能性があると聞きました。

それを達成する方法は?

37
pajton

これを試してください(Google Testドキュメントから直接...):

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

これは古いのはわかっていますが、今日も同じ答えを探していました。 「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;
_

これは、前の回答で述べたように、各テストが独自のクラスであるため機能します。

25
Ralfizzle

はるかに優れた戦略は、単体テストの中で友達テストを許可しないことです。

フレンドテストにプライベートメンバーへのアクセスを許可すると、コードベースが保守しにくくなります。コンポーネントの内部実装の詳細がリファクタリングされるたびに壊れるテストは、あなたが望むものではありません。代わりに、パブリックインターフェイスを介してコンポーネントをテストできるデザインを取得するために余分な労力が費やされると、コンポーネントのパブリックインターフェイスが更新されるたびに更新のみが必要なテストが得られます。

gtest/gtest_prod.hに依存するテストは、設計が不十分であることを示すものと見なされます。

6
Martin G

テストしたクラスとテストクラスが異なる名前空間にある場合(たとえば、テストがグローバル名前空間にある場合)、テストクラスを前方宣言して、FRIEND_TESTに名前空間プレフィックスを追加する必要がある場合があります。

// foo.h
#include <gtest/gtest_prod.h>

class FooTest_BarReturnsZeroOnNull_Test;

// Defines FRIEND_TEST.
class my_namespace::Foo {
  ...
 private:
  FRIEND_TEST(::FooTest, BarReturnsZeroOnNull);
  int Bar(void* x);
};

// 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++の親しみやすさ)とホワイトボックステストは物議を醸す問題であることは知っていますが、複雑で科学的なアルゴリズムに取り組む場合、各ステップでテストと検証を行う必要がありますが、その必要はありません。公開(または保護された)インターフェイスで公開したくない場合、フレンドテストは、特にテスト駆動型の開発アプローチでは、シンプルで実用的なソリューションのように見えます。親しみやすさやホワイトボックステストを使用するという信条に反する場合は、後でコードをリファクタリングする(またはホワイトボックステストを完全に削除する)ことが常に可能です。

1
Corentor