web-dev-qa-db-ja.com

Googleテストフィクスチャのコンストラクター引数を指定する

Googleテストで、さまざまなテストケースで使用するテストフィクスチャを指定したいと思います。フィクスチャは、クラスTheClassおよびそのデータ管理クラスTheClassDataのオブジェクトを割り当ておよび割り当て解除します。データ管理クラスは、データファイルの名前を必要とします。
テストごとに、ファイル名は異なる必要があります。

次のフィクスチャを定義しました:

class TheClassTest : public ::testing::Test {
 protected:
  TheClassTest(std::string filename) : datafile(filename) {}
  virtual ~TheClassTest() {}
  virtual void SetUp() {
    data = new TheClassData(datafile);
    tc = new TheClass(data);
  }
  virtual void TearDown() {
    delete tc;
    delete data;
  }

  std::string datafile;
  TheClassData* data;
  TheClass* tc;
};

現在、異なるテストでは、異なるファイル名のフィクスチャを使用する必要があります。これをテスト環境のセットアップと想像してください。

質問:テストからファイル名を指定するにはどうすればよいですか、つまり、フィクスチャのデフォルト以外のコンストラクタを呼び出す方法は?

::testing::TestWithParam<T>TEST_Pのようなものが見つかりましたが、1つのテストを異なる値で実行するのではなく、1つのフィクスチャで異なるテストを実行する必要があるため、役に立ちません。

11
Gregor

別のユーザーが提案したように、デフォルト以外のコンストラクターを使用してフィクスチャーをインスタンス化しても、希望どおりの結果は得られません。ただし、他の方法もあります。単にSetUp関数をオーバーロードし、テストでそのバージョンを明示的に呼び出します。

class TheClassTest : public ::testing::Test {
protected:
    TheClassTest() {}
    virtual ~TheClassTest() {}
    void SetUp(const std::string &filename) {
        data = new TheClassData(filename);
        tc = new TheClass(data);
    }
    virtual void TearDown() {
        delete tc;
        delete data;
    }

    TheClassData* data;
    TheClass* tc;
};

テストでは、このオーバーロードを使用してファイル名を設定します。

TEST_F(TheClassTest, MyTestCaseName)
{
    SetUp("my_filename_for_this_test_case");

    ...
}

パラメータなしのTearDownは、テストが完了すると自動的にクリーンアップされます。

8
Marko Popovic

現在のクラスをフィクスチャの基本クラスとして使用します。

class TheClassTestBase : public ::testing::Test {
 protected:
  TheClassTestBase(std::string filename) : datafile(filename) {}
  ...
 };

特定のファイル名ごとに、派生フィクスチャを使用します。

class TheClassTestForFooTxt : public TheClassTestBase {
protected:
    TheClassTestForFooTxt() : TheClassTestBase ("foo.txt") {}
};

ただし、これはすべてのパラメーターセットに必要な追加の手順です。したがって、テンプレートまたはマクロを使用して、少ない労力でそれを実行できます。お気に入り:

template <typename ClassTestTag>
struct ClassTestParams
{
    static std::string filename;
};

template<typename  ClassTestTag>
class TheClassTest : public TheClassTestBase {
protected:
    TheClassTest() : TheClassTestBase (ClassTestParams<ClassTestTag>::filename) {}
};

次に、すべてのパラメータセットについて、次のようにします。

class FooTxtTag {};
template <> std::string ClassTestParams<FooTxtTag>::value = "foo.txt";
using TheClassTestForFooTxt = TheClassTest<FooTxtTag>;
TEST_F(TheClassTestForFooTxt, xxxx) {}

ただし、特定のケースでは GoogleTest:type-parameterized-tests も試してみます。

3
PiotrNycz

これに対処するもう1つの優れた方法は、フィクスチャを拡張し、拡張されたクラスで、必要な引数で古いコンストラクタを呼び出す新しいデフォルトコンストラクタを提供することです。例えば:

struct MySpecializedTestFixture : public GenericTestFixture
{
  MySpecializedTestFixture() : GenericTestFixture("a thing", "another thing") {}
};

TEST_F(MySpecializedTestFixture, FancyTest)
{
  // Use the thing environment and make some assertions.
}
1
mikepurvis

この特定のケースでは、テストフィクスチャを完全に取り除くほうがはるかに簡単だと思います。 SetUp関数は、代わりに、必要なファイル名でクラスをインスタンス化するヘルパー関数で置き換えることができます。これにより、TEST_PまたはTEST_Fの代わりにTESTを使用できます。これで、各テストケースはスタンドアロンテストになり、ヘルパー関数を使用して、またはテストケースの本文に直接、独自のテストクラスインスタンスを作成します。

例えば:

using namespace testing;
TEST(FooClassTest, testCase1)
{
    FooClass fooInstance("File_name_for_testCase1.txt");
    /* The test case body*/
    delete fooInstance;
}
0
Muthu Narayanan

提案されているようにSetUpメソッドをオーバーロード here し、オーバーロードしたSetUpを必ず使用するようにしたい場合は、TearDownメソッドでアサーションを使用できます。

class my_fixture : public ::testing::Test
{
protected:
    bool SETUP_HIT_FLAG = false;

    void SetUp(double parameter)
    {
        ...
        SETUP_HIT_FLAG = true;
    }

    void TearDown() override
    {
        assert(SETUP_HIT_FLAG && "You forgot to call SetUp with your parameter!");
    }
};
0
learnvst