Life, Education, Death

プログラミング以外でも思ったことをつらつらと書きたい

C++のテストフレームワークを調べてみる

無難にgoogle testを使うか、cspecで新しいことを始めるかといった選択でしょうか・・・。

google test framework

cppunitよりもスマートな印象。基本機能に大きな違いはないですが、google testの悪いところが今のところ見つからないので、cppunitの代わりに使うのはありな気がする。

ここにアサート文についてはここに一覧がまとまっていた。

簡単に気になる機能をgoogle testの翻訳ドキュメント
から引っ張ってきました。

値をパラメータ化したテスト

こんな値をちょっと変えたテストを行いたいときの構文が用意されています。

void TestFooHelper(bool flag_value) {
  flag = flag_value;
  // foo() をテストするコード.
}

TEST(MyCodeTest, TestFooo) {
  TestFooHelper(false);
  TestFooHelper(true);
}

定義がこれ。

class FooTest : public ::testing::TestWithParam<const char*> {

TEST_P(FooTest, DoesBlah) {
  EXPECT_TRUE(foo.Blah(GetParam()));
}

};

テストの宣言はこれ。

INSTANTIATE_TEST_CASE_P(InstantiationName,
                        FooTest,
                        ::testing::Values("meeny", "miny", "moe"));

外から渡されるパラメータは、TEST_Pマクロの中でGetParam()関数から取得できる。
こういうことをしたいときは多々あるので便利ですね。

また、型違いのものを実行したい場合は、下のようにテストを定義して

TYPED_TEST(FooTest, DoesBlah) {
  // テスト内部で型パラメータを取得するには,特別な名前 TypeParam を参照します.
  // 派生クラステンプレート内部なので,FooTest のメンバにアクセスするには
  // 'this' を使う必要があります.
  TypeParam n = this->value_;

  // フィクスチャの static なメンバにアクセスするには,
  // 'TestFixutre::' プリフィックスを追加します.
  n += TestFixture::shared_;

  // フィクスチャ内で typedef されたメンバにアクセスするには,'typename TestFixture::' プリフィックスを追加します.
  // 'typename' は,コンパイラに型名であることを知らせるためにあります.
  typename TestFixture::List values;
  values.push_back(n);
  ...
}

こんな感じで、型をパラメータとして渡します。

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


上級ガイド — Google Test ドキュメント日本語訳より

CSpec

RSpecのような書き方のできるテストフレームワークもありました。
テストを読みやすくするという点で、 とても気に入っています。Cでも同じ書き方が出来るのはポイントが高い。

まだ、詳しい仕組みを確認していないので採用できないかもしれないですが・・・。

#include <stdio.h>
#include <string.h>
#include "cspec.h"
#include "cspec_output_verbose.h"

DESCRIBE(strcmp, "int strcmp ( const char * str1, const char * str2 )")

	IT( "returns 0 only when strings are equal" )
		SHOULD_EQUAL( strcmp("hello", "hello"), 0)
		SHOULD_NOT_EQUAL( strcmp("hello", "world"), 0)
	END_IT

	IT( "returns a negative integer when str1 is less than str2"  )
		SHOULD_BE_TRUE( strcmp("hello", "world") < 0 )
		SHOULD_BE_TRUE( strcmp("0123", "1321431") < 0 )
	END_IT

	IT( "returns a positive integer if str1 is greater than str2"  )
		SHOULD_BE_TRUE( strcmp("yellow", "world") > 0 )
		SHOULD_BE_TRUE( strcmp("9", "789") > 0 )
	END_IT

END_DESCRIBE

void main()
{
	CSpec_Run( DESCRIPTION( strcmp ), CSpec_NewOutputVerbose() );
}

CSpec : Behavior-driven development in C · arnaudbrejeon/cspec Wiki · GitHub