Google C++ユニットテストフレームワーク(Gtest)シリーズチュートリアルの3-テストファームウェア(Test fixture)
8775 ワード
引用する
『Google C++ユニットテストフレームワーク(Gtest)シリーズチュートリアルの2——断言、関数テスト』では,断言文とTEST()を用いて関数テストを行う方法を理解し,TEST()の使用では,1つのテスト例が複数のテスト例を含む組織方式に触れた.複数のテスト・インスタンスでは、既知のデータ構成と初期化操作が必要になる場合があります.そのため、Gtestはテスト・ファームウェア(Test fixture)を提供し、データ管理を支援します.
「立ち後れ」の方法
テストファームウェアを理解する前に、次のテスト例を見てみましょう.
以上のQueueクラスをテストすると仮定し、以前に学習したTEST()の使い方に基づいて、テストコードを以下のように記述します.
あなたはすでに問題の所在を発見しましたか?はい、赤いフォントのテストデータ初期化部分に重複コードがあります!この例には2つのテストインスタンスしか含まれていません.重複コードの問題は際立っていませんが、数十個以上のテストインスタンスでは、初期化データを管理する別の方法が必要です.
テストファームウェア(Test fixture)
テストファームウェアの役割は、2つ以上のテストインスタンスで使用されるデータを管理し、テストファームウェアを使用して上記のテストを完了する方法です.
まず、一般的なファームウェアクラスはFooTestとして命名され、Fooは被測定クラスの名前であるファームウェアクラス(fixture class)を定義する必要があります.
ファームウェアクラスを定義する方法は、次のとおりです.は、クラスのサブクラスがクラスのデータにアクセスできるようにpublicまたはprotectedをアクセス制御識別として使用する、test::Testから継承されたクラスを書く. このクラスでは、テストインスタンスが使用するデータを定義する. SetUp()メソッドまたはデフォルトコンストラクション関数を使用してデータ初期化操作を行い、TearDown()メソッドまたはコンストラクション関数を使用してデータクリーンアップ操作を行い、SetUp()とTearDown()のスペルに注意する. 必要に応じて、初期化データのようにクラスにメンバー関数を定義することもできます.ここで定義したメンバー関数は、テストインスタンスによって繰り返し使用することもできます.
次に、対応するテストインスタンスを作成する方法について説明します.まず、新しいマクロを使用します.
TEST_F()は、2つのパラメータの意味がTEST()のパラメータの意味と同じであるが、TEST_F()の最初のパラメータは、ファームウェアクラスの名前である必要があります.
上記QueTestテストファームウェアと組み合わせて、テストコードを以下のように作成します.
TEST_がわかりますF()の使用方法はTEST()と大きく異なりません.上記の2つのテストインスタンスが実行されると、Gtestは以下のことをしました. QueTestオブジェクト(t 1と仮定)を構築する. はt 1を呼び出す.SetUp()は、t 1オブジェクトを初期化する. の最初の試験例(IsEmptyInitially)は、t 1を用いて試験される. はt 1を呼び出す.TearDown()はデータの整理を行う; 廃棄対象t 1; 新しいQueTestオブジェクトを作成し、次のテストインスタンスDequeueWorksについて上記の手順を繰り返します.
Gtestは、ファームウェアクラスオブジェクトを作成および破棄することによって、各テストインスタンスに独立した初期化データを作成します.上記の2つのテストスキームの目的と結果はまったく同じですが、シナリオ2は、テストファームウェアを使用することによって、データ初期化による重複コードを根絶します.
ファームウェアクラス(Fixture class)
C++クラスは継承可能な特徴を持っており、このようにファームウェアクラスを柔軟に定義することができ、複数のファームウェアクラスが共有する特性を抽象化してベースクラスを形成し、コード多重化、データ多重化の効果をさらに達成することができ、次の例を見てみましょう.
このファームウェアクラスは、テストインスタンスの実行時間を簡単に分析し、SetUp()がテストインスタンスの実行前に実行し、TearDown()がテストインスタンスの実行後に実行するという特徴を利用し、実行時間が5秒を超えるテストインスタンスは検出に失敗します.SetUp()とTearDown()関数でも断言文を使用することができることに注意してください.
Queueクラスのテストインスタンスに実行時間制限があると仮定すると、QuickTestから継承されたファームウェアクラスを記述できます.
このように定義すると、QueTestに関連付けられたテストインスタンスが実行されると、その実行時間が検出されます.
小結
Gtestテストファームウェア(Test fixture)を用いた理由と方法を紹介し,最後にクラス継承によりテストファームウェアを柔軟に定義できることを提案した.次のセクションでは、Gtest値のパラメータ化、タイプのパラメータ化の使用方法について説明します.Reference: googletest project
『Google C++ユニットテストフレームワーク(Gtest)シリーズチュートリアルの2——断言、関数テスト』では,断言文とTEST()を用いて関数テストを行う方法を理解し,TEST()の使用では,1つのテスト例が複数のテスト例を含む組織方式に触れた.複数のテスト・インスタンスでは、既知のデータ構成と初期化操作が必要になる場合があります.そのため、Gtestはテスト・ファームウェア(Test fixture)を提供し、データ管理を支援します.
「立ち後れ」の方法
テストファームウェアを理解する前に、次のテスト例を見てみましょう.
template <typename E> // E is the element type.
class Queue {
public:
Queue();
void Enqueue(const E& element);
E* Dequeue(); // Returns NULL if the queue is empty.
size_t size() const;
...
};
以上のQueueクラスをテストすると仮定し、以前に学習したTEST()の使い方に基づいて、テストコードを以下のように記述します.
//
TEST(QueueTest, IsEmptyInitially) {
Queue<int> q0_;
EXPECT_EQ(0, q0_.size());
}
TEST(QueueTest, DequeueWorks) {
Queue<int> q0_;
Queue<int> q1_;
Queue<int> q2_;
q1_.Enqueue(1);
q2_.Enqueue(2);
q2_.Enqueue(3);
int* n = q0_.Dequeue();
EXPECT_EQ(NULL, n);
n = q1_.Dequeue();
ASSERT_TRUE(n != NULL);
EXPECT_EQ(1, *n);
EXPECT_EQ(0, q1_.size());
delete n;
n = q2_.Dequeue();
ASSERT_TRUE(n != NULL);
EXPECT_EQ(2, *n);
EXPECT_EQ(1, q2_.size());
delete n;
}
あなたはすでに問題の所在を発見しましたか?はい、赤いフォントのテストデータ初期化部分に重複コードがあります!この例には2つのテストインスタンスしか含まれていません.重複コードの問題は際立っていませんが、数十個以上のテストインスタンスでは、初期化データを管理する別の方法が必要です.
テストファームウェア(Test fixture)
テストファームウェアの役割は、2つ以上のテストインスタンスで使用されるデータを管理し、テストファームウェアを使用して上記のテストを完了する方法です.
まず、一般的なファームウェアクラスはFooTestとして命名され、Fooは被測定クラスの名前であるファームウェアクラス(fixture class)を定義する必要があります.
class QueueTest : public ::testing::Test {
protected:
virtual void SetUp() {
q1_.Enqueue(1);
q2_.Enqueue(2);
q2_.Enqueue(3);
}
// virtual void TearDown() {}
Queue<int> q0_;
Queue<int> q1_;
Queue<int> q2_;
};
ファームウェアクラスを定義する方法は、次のとおりです.
次に、対応するテストインスタンスを作成する方法について説明します.まず、新しいマクロを使用します.
TEST_F(test_case_name, test_name) {
... test body ...
}
TEST_F()は、2つのパラメータの意味がTEST()のパラメータの意味と同じであるが、TEST_F()の最初のパラメータは、ファームウェアクラスの名前である必要があります.
上記QueTestテストファームウェアと組み合わせて、テストコードを以下のように作成します.
//
TEST_F(QueueTest, IsEmptyInitially) {
EXPECT_EQ(0, q0_.size());
}
TEST_F(QueueTest, DequeueWorks) {
int* n = q0_.Dequeue();
EXPECT_EQ(NULL, n);
n = q1_.Dequeue();
ASSERT_TRUE(n != NULL);
EXPECT_EQ(1, *n);
EXPECT_EQ(0, q1_.size());
delete n;
n = q2_.Dequeue();
ASSERT_TRUE(n != NULL);
EXPECT_EQ(2, *n);
EXPECT_EQ(1, q2_.size());
delete n;
}
TEST_がわかりますF()の使用方法はTEST()と大きく異なりません.上記の2つのテストインスタンスが実行されると、Gtestは以下のことをしました.
Gtestは、ファームウェアクラスオブジェクトを作成および破棄することによって、各テストインスタンスに独立した初期化データを作成します.上記の2つのテストスキームの目的と結果はまったく同じですが、シナリオ2は、テストファームウェアを使用することによって、データ初期化による重複コードを根絶します.
ファームウェアクラス(Fixture class)
C++クラスは継承可能な特徴を持っており、このようにファームウェアクラスを柔軟に定義することができ、複数のファームウェアクラスが共有する特性を抽象化してベースクラスを形成し、コード多重化、データ多重化の効果をさらに達成することができ、次の例を見てみましょう.
class QuickTest : public testing::Test {
protected:
// This is a good place to record the start time.
virtual void SetUp() {
start_time_ = time(NULL);
}
// check if the test was too slow.
virtual void TearDown() {
// Gets the time when the test finishes
const time_t end_time = time(NULL);
// Asserts that the test took no more than ~5 seconds.
EXPECT_TRUE(end_time - start_time_ <= 5) << "The test took too long.";
}
このファームウェアクラスは、テストインスタンスの実行時間を簡単に分析し、SetUp()がテストインスタンスの実行前に実行し、TearDown()がテストインスタンスの実行後に実行するという特徴を利用し、実行時間が5秒を超えるテストインスタンスは検出に失敗します.SetUp()とTearDown()関数でも断言文を使用することができることに注意してください.
Queueクラスのテストインスタンスに実行時間制限があると仮定すると、QuickTestから継承されたファームウェアクラスを記述できます.
class QueueTest : public QuickTest {
//......
};
このように定義すると、QueTestに関連付けられたテストインスタンスが実行されると、その実行時間が検出されます.
小結
Gtestテストファームウェア(Test fixture)を用いた理由と方法を紹介し,最後にクラス継承によりテストファームウェアを柔軟に定義できることを提案した.次のセクションでは、Gtest値のパラメータ化、タイプのパラメータ化の使用方法について説明します.Reference: googletest project