読者です 読者をやめる 読者になる 読者になる

Natural Software

KinectなどのDepthセンサーを中心に活動しています

GoogleTest をいろいろ使ってみる

TDD C++

Visual Studio で GoogleTest を使う - かおるんダイアリー
先日試したGoogleTestをもう少し触ってみました。


Primer - googletest - Getting started with Google C++ Testing Framework - Google C++ Testing Framework - Google Project Hosting
このページにあるものが一通りだと思うのでサンプルっぽく仕上げてみました。
ソースはgithubにあります。
http://github.com/kaorun/gtestSample

GoogleTest で使える項目(説明ページより抜粋とサンプルコード)

Basic Assertions

true/falseで判定する

致命的な判定 致命的ではない判定 判定条件
ASSERT_TRUE(condition); EXPECT_TRUE(condition); condition が true のとき成功
ASSERT_FALSE(condition); EXPECT_FALSE(condition); condition が false のとき成功
#include <gtest/gtest.h>

// EXPECT_TRUE
TEST( BasicAssertion, EXPECT_TRUE )
{
  EXPECT_TRUE( true );  // 結果がtrueなら成功
  EXPECT_TRUE( false ); // 結果がfalseなら失敗
}

// EXPECT_FALSE
TEST( BasicAssertio, EXPECT_FALSE )
{
  EXPECT_FALSE( false ); // 結果がfalseなら成功
  EXPECT_FALSE( true );  // 結果がtrueなら失敗
}

致命的な判定(ASSERT_*)と致命的ではない判定(EXPECT_*)の違いは、致命的な判定の場合は失敗したらそのテストが終了する、致命的ではない判定の場合は、そのままテストは続行される。

Binary Comparison

2値の比較で判定する

致命的な判定 致命的ではない判定 判定条件
ASSERT_EQ(expected, actual); EXPECT_EQ(expected, actual); expected == actual のとき成功
ASSERT_NE(val1, val2); EXPECT_NE(val1, val2); val1 != val2 のとき成功
ASSERT_LT(val1, val2); EXPECT_LT(val1, val2); val1 < val2 のとき成功
ASSERT_LE(val1, val2); EXPECT_LE(val1, val2); val1 <= val2 のとき成功
ASSERT_GT(val1, val2); EXPECT_GT(val1, val2); val1 > val2 のとき成功
ASSERT_GE(val1, val2); EXPECT_GE(val1, val2); val1 >= val2 のとき成功
#include <gtest/gtest.h>

TEST( BinaryAssertions, EXPECT_EQ )
{
  EXPECT_EQ( 1, 1 );  // expectd == actual なら成功
  EXPECT_EQ( 2, 3 );  // expectd != actual なら失敗
}

TEST( BinaryAssertions, EXPECT_NE )
{
  EXPECT_NE( 2, 3 );  // expectd != actual なら成功
  EXPECT_NE( 1, 1 );  // expectd == actual なら失敗
}

TEST( BinaryAssertions, EXPECT_LT )
{
  EXPECT_LT( 2, 3 );  // expectd < actual なら成功
  EXPECT_LT( 4, 4 );  // expectd == actual なら失敗
  EXPECT_LT( 5, 4 );  // expectd > actual なら失敗
}

TEST( BinaryAssertions, EXPECT_LE )
{
  EXPECT_LE( 2, 3 );  // expectd < actual なら成功
  EXPECT_LE( 4, 4 );  // expectd == actual なら成功
  EXPECT_LE( 5, 4 );  // expectd > actual なら失敗
}

TEST( BinaryAssertions, EXPECT_GT )
{
  EXPECT_GT( 3, 2 );  // expectd > actual なら成功
  EXPECT_GT( 4, 4 );  // expectd == actual なら失敗
  EXPECT_GT( 4, 5 );  // expectd < actual なら失敗
}

TEST( BinaryAssertions, EXPECT_GE )
{
  EXPECT_GE( 3, 2 );  // expectd > actual なら成功
  EXPECT_GE( 4, 4 );  // expectd == actual なら成功
  EXPECT_GE( 4, 5 );  // expectd < actual なら失敗
}
String Comparison

2つのC言語文字列を比較する。

致命的な判定 致命的ではない判定 判定条件
ASSERT_STREQ(expected_str, actual_str); EXPECT_STREQ(expected_str, actual_str); 2つの文字列が同じであれば成功(大文字、小文字を区別する)
ASSERT_STRNE(str1, str2); EXPECT_STRNE(str1, str2); 2つの文字列が異なっていれば成功(大文字、小文字を区別する)
ASSERT_STRCASEEQ(expected_str, actual_str); EXPECT_STRCASEEQ(expected_str, actual_str); 2つの文字列が同じであれば成功(大文字、小文字を区別しない)
ASSERT_STRCASENE(str1, str2); EXPECT_STRCASENE(str1, str2); 2つの文字列が異なっていれば成功(大文字、小文字を区別しない)
#include <gtest/gtest.h>

TEST( StringComparison, EXPECT_STREQ )
{
  EXPECT_STREQ( "abcd", "abcd" );  // 同じ文字列であれば成功
  EXPECT_STREQ( "abcd", "bcde" );  // 違う文字列であれば失敗
  EXPECT_STREQ( "abcd", "ABCD" );  // 同じ文字列でも、大文字、小文字の違いは失敗
}

TEST( StringComparison, EXPECT_STRNE )
{
  EXPECT_STRNE( "abcd", "bcde" );  // 違う文字列であれば成功
  EXPECT_STRNE( "abcd", "ABCD" );  // 同じ文字列でも、大文字、小文字の違いは成功
  EXPECT_STRNE( "abcd", "abcd" );  // 同じ文字列であれば失敗
}

TEST( StringComparison, EXPECT_STRCASEEQ )
{
  EXPECT_STRCASEEQ( "abcd", "abcd" );  // 同じ文字列であれば成功
  EXPECT_STRCASEEQ( "abcd", "bcde" );  // 違う文字列であれば失敗
  EXPECT_STRCASEEQ( "abcd", "ABCD" );  // 同じ文字列で、大文字、小文字の違いは成功
}

TEST( StringComparison, EXPECT_STRCAENE )
{
  EXPECT_STRCASENE( "abcd", "bcde" );  // 違う文字列であれば成功
  EXPECT_STRCASENE( "abcd", "ABCD" );  // 同じ文字列で、大文字、小文字の違いは失敗
  EXPECT_STRCASENE( "abcd", "abcd" );  // 同じ文字列であれば失敗
}

テストフィクスチャ

一般的なxUnitのようにSetUpやTearDownを利用したい場合は、テストクラスを作成する

#include <gtest/gtest.h>
#include <iostream>

//ターゲットクラス
class Foo {
public:
  Foo() : value_( 0 ) {}

  void set( int value ) { value_ = value; }
  int get() const { return value_; }

private:

  int value_;
};

// テストクラス
class FooTest : public ::testing::Test {
public:

  // テスト前にさせたいこと
  virtual void SetUp() {
    std::cout << "FooTest::SetUp" << std::endl;
  }

  // テスト後にさせたいこと
  virtual void TearDown() {
    std::cout << "FooTest::TearDown" << std::endl;
  }

  // 継承して最終的なテストクラスを作成するようなので、protectedにしておく
protected:

  Foo foo_;
};

TEST_F( FooTest, get ) 
{
  EXPECT_EQ( foo_.get(), 0 );
}

TEST_F( FooTest, set )
{
  foo_.set( 2 );
  EXPECT_EQ( foo_.get(), 2 );
}