#12 Google Test 備忘録

  C++ Test  [公開]
icon Kenichi TAGI が 2018/06/22 22:57 に投稿 ( icon Kenichi TAGI が 2018/09/19 19:13 に編集 <更新履歴> )
  投稿を編集(サインイン)
  ストック
  アンケート回答

  目次

はじめに

Google Test は Google 製の C++ Test Framework です。
導入については良質な解説ページがいくらでもあるので省略、ここではいつのまにか忘れてしまう事柄や、実際に使用して得た知見を備忘のために残します。

備忘録

テストケース名、テスト名について

どちらも有効な C++ の識別子でなければならず、アンダースコア(_)を使用してはいけません。Google Test ではテストの名前解決のためにアンダースコア(_)を用いて名前を連結しており、ユーザがこれに干渉するのを避けるためです。よって、テストケース名、テスト名は必然的に Camel Case(Pascal Case)となります。

参考: なぜ,テストケース名やテスト名にアンダースコアを利用してはいけないのでしょうか?

テストを一時的に無効にする

テストに DISABLED_ プレフィックスをつけることにより、テストを一時的に無効化することができます。これはテストケースにも有効です。テストケース名はすなわちテストフィクチャ(クラス)名ですので昨今の IDE であれば rename 機能で属するテストを一括で無効化できます。

テスト実行後に DISABLED なテスト(実行しなかったテスト)がレポートされるので、#if 0 で無効化するよりも安全です。

参考: テストを一時的に無効にする

メッセージ出力

ユーザ定義の失敗メッセージを出力するには、 <<演算子 を用いてメッセージをストリームに出力します。

メッセージ出力の例:

ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";

for (int i = 0; i < x.size(); ++i) {
  EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
}

明示的な成功と失敗

FAIL() は致命的な失敗を生成します。ADD_FAILURE() および ADD_FAILURE_AT() は致命的ではない失敗を生成します。プログラムの制御フローによって成功/失敗を判断するときに使用します。

制御フローによって判断する例:

switch(expression) {
  case 1: ... some checks ...
  case 2: ... some other checks
  ...
  default: FAIL() << "We shouldn't get here.";

SUCCEED() は成功を生成します。テスト全体を成功させるわけではなく、テスト実行時にそこに含まれるすべてのアサーションが失敗しなかった場合にのみ、そのテスト全体が成功したとみなします。

参考: 明示的な成功と失敗

Private メンバのテスト

private なクラスメンバはそのクラスや friend クラスからのみアクセス可能です。クラスの private メンバにアクセスするにはテストフィクスチャをそのクラスの friend に宣言して、フィクスチャクラスにアクセサを定義します。

実装例:

#ifdef WITH_GTEST
#include "gtest/gtest_prod.h"
#endif

template <class T, int N=10>
class Stack {
  T data_[N];
  int index_;

#ifdef WITH_GTEST
  friend class StackTestF;
#endif
  ...
class StackTestF : public ::testing::Test {
protected:
  template <class T>
  auto get_index(T& s) {
    return s.index_;
  }
  ...

参考: Private クラスメンバ

型付けテスト

同じテストロジックを異なる型に対して繰り返したい場合はフィクスチャクラスをテンプレート化します。上記の StackTestF を char型、int型、unsigned int型 でテストできるようにしてみます。

まずはフィクスチャクラスのテンプレート化から。

template <class T>
class StackTestF : public ::testing::Test {
protected:
    template <class U>
    int get_index(U& s) { return s.index_; }
    static const int num_ = 3;
};
template <class T> const int StackTestF<T>::num_;

次にテストする型とテストケースを関連付けます。

typedef ::testing::Types<char, int, unsigned int> MyTypes;
TYPED_TEST_CASE(StackTestF, MyTypes);

テストケースは TEST_F() の代わりに TYPED_TEST_CASE() を使います。

TYPED_TEST(StackTestF, PushOver) {
    // テストケース内で型を取得するには TypeParam を使う
    // static なクラスメンバにアクセスするには TestFixture:: を付与する
    Stack<TypeParam, TestFixture::num_> s;
    for (int i=0; i<TestFixture::num_; ++i)
        s.push('a');
    s.push('b');
    // StackTestF のメンバにアクセスするには this を使う(派生クラステンプレート内部なので)
    EXPECT_EQ(TestFixture::num_, this->get_index(s));
}

実行結果:

[==========] Running 6 tests from 3 test cases.
[----------] Global test environment set-up.
[----------] 2 tests from StackTestF/0, where TypeParam = char
[ RUN      ] StackTestF/0.PushOver
[       OK ] StackTestF/0.PushOver (0 ms)
[ RUN      ] StackTestF/0.PopUnder
[       OK ] StackTestF/0.PopUnder (0 ms)
[----------] 2 tests from StackTestF/0 (0 ms total)

[----------] 2 tests from StackTestF/1, where TypeParam = int
[ RUN      ] StackTestF/1.PushOver
[       OK ] StackTestF/1.PushOver (0 ms)
[ RUN      ] StackTestF/1.PopUnder
[       OK ] StackTestF/1.PopUnder (0 ms)
[----------] 2 tests from StackTestF/1 (0 ms total)

[----------] 2 tests from StackTestF/2, where TypeParam = unsigned int
[ RUN      ] StackTestF/2.PushOver
[       OK ] StackTestF/2.PushOver (0 ms)
[ RUN      ] StackTestF/2.PopUnder
[       OK ] StackTestF/2.PopUnder (0 ms)
[----------] 2 tests from StackTestF/2 (0 ms total)

[----------] Global test environment tear-down
[==========] 6 tests from 3 test cases ran. (0 ms total)
[  PASSED  ] 6 tests.

char型、int型、unsigned int型 でテストされてます。

参考: 型付けテスト

テストの部分的な実行

デフォルトでは、Google Test はユーザが定義したすべてのテストを実行します。GTEST_FILTER 環境変数、または --gtest_filter フラグでフィルタ文字列を設定するとこれにマッチしたテストケース、テストを実行します。

フラグ(フィルタ文字列)の指定例:

フラグ(フィルタ文字列)説明
./foo_testフラグの指定なし。すべてのテストを実行する
./foo_test —gtest_filter=** は任意の文字列にマッチ。すべてのテストを実行する
./foo_test —gtest_filter=FooTest.*テストケース FooTest 内の全てのテストを実行する
./foo_test —gtest_filter=*Null*:*Constructor*完全な名前に "NULL"、または "Constructor" を含むテストを全て実行する
./foo_test —gtest_filter=-*DeathTest.*Death テスト 以外 を実行する
./foo_test —gtest_filter=FooTest.*-FooTest.Barテストケース FooTest 内の全てのテストを実行する。ただし、FooTest.Bar は除く

参考: テストの部分的な実行

ヘルプを表示する

サポートされているフラグと使い方の一覧をみるにはテストプログラムに --help フラグをつけて実行します。

おわりに

上記、Private クラスメンバへのアクセスを含んだ簡単なテストを実行するサンプルを以下に置きました。

Samples for JSP-knowledge

来たるべきときに備えて、本ページと合わせてリポジトリも拡充していけたらと思っています。

 添付ファイル     - [0]


 コメント追加