「Google Test」の版間の差分

提供: C++入門
移動: 案内検索
 
(同じ利用者による、間の2版が非表示)
行13: 行13:
 
== 概要 ==
 
== 概要 ==
  
Google C++ Testing Framework です。
+
Google [[C++]] Testing Framework です。
  
 
赤と緑のカラー表示で、コンソールでも賑やかでステキです。
 
赤と緑のカラー表示で、コンソールでも賑やかでステキです。
行34: 行34:
  
 
が作成されます。
 
が作成されます。
 +
 +
== アサーション ==
 +
 +
[[Google Test]] のアサーションは、マクロです。動作を調べるために、アサーションを利用します。
 +
 +
ASSERT_* バージョンが失敗した場合は、致命的な失敗となり、実行中の関数を中断します。
 +
EXPECT_* バージョンが失敗した場合は、致命的ではない失敗となり、関数を中断しません。
 +
 +
=== 基本的なアサーション ===
 +
 +
{|class="wikitable"
 +
|+ 基本的なアサーション
 +
!致命的なアサーション
 +
!致命的ではないアサーション
 +
!検証内容
 +
|----
 +
|ASSERT_TRUE(condition);
 +
|EXPECT_TRUE(condition);
 +
|condition が true
 +
|----
 +
|ASSERT_FALSE(condition);
 +
|EXPECT_FALSE(condition);
 +
|condition が false
 +
|----
 +
|}
 +
 +
=== 2つの値の比較 ===
 +
 +
{|class="wikitable"
 +
|+ 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
 +
|----
 +
|}
 +
 +
=== 文字列の比較 ===
 +
 +
{|class="wikitable"
 +
|+ 文字列の比較
 +
!致命的なアサーション
 +
!致命的ではないアサーション
 +
!検証内容
 +
|----
 +
|ASSERT_STREQ(expected_str, actual_str);
 +
|EXPECT_STREQ(expected_str, actual_str);
 +
|2つの C 文字列の内容が等しい
 +
|----
 +
|ASSERT_STRNE(str1, str2);
 +
|EXPECT_STRNE(str1, str2);
 +
|2つの C 文字列の内容が等しくない
 +
|----
 +
|ASSERT_STRCASEEQ(expected_str, actual_str);
 +
|EXPECT_STRCASEEQ(expected_str, actual_str);
 +
|大文字小文字を無視した場合,2つの C 文字列の内容が等しい
 +
|----
 +
|ASSERT_STRCASENE(str1, str2);
 +
|EXPECT_STRCASENE(str1, str2);
 +
|大文字小文字を無視した場合,2つの C 文字列の内容が等しくない
 +
|----
 +
|}
 +
 +
== main()関数を書く ==
 +
 +
 +
<syntaxhighlight lang="cpp">
 +
#include "this/package/foo.h"
 +
#include "gtest/gtest.h"
 +
 +
namespace {
 +
 +
// The fixture for testing class Foo.
 +
class FooTest : public ::testing::Test {
 +
protected:
 +
  // You can remove any or all of the following functions if its body
 +
  // is empty.
 +
 +
  FooTest() {
 +
    // You can do set-up work for each test here.
 +
  }
 +
 +
  virtual ~FooTest() {
 +
    // You can do clean-up work that doesn't throw exceptions here.
 +
  }
 +
 +
  // If the constructor and destructor are not enough for setting up
 +
  // and cleaning up each test, you can define the following methods:
 +
 +
  virtual void SetUp() {
 +
    // Code here will be called immediately after the constructor (right
 +
    // before each test).
 +
  }
 +
 +
  virtual void TearDown() {
 +
    // Code here will be called immediately after each test (right
 +
    // before the destructor).
 +
  }
 +
 +
  // Objects declared here can be used by all tests in the test case for Foo.
 +
};
 +
 +
// Tests that the Foo::Bar() method does Abc.
 +
TEST_F(FooTest, MethodBarDoesAbc) {
 +
  const string input_filepath = "this/package/testdata/myinputfile.dat";
 +
  const string output_filepath = "this/package/testdata/myoutputfile.dat";
 +
  Foo f;
 +
  EXPECT_EQ(0, f.Bar(input_filepath, output_filepath));
 +
}
 +
 +
// Tests that Foo does Xyz.
 +
TEST_F(FooTest, DoesXyz) {
 +
  // Exercises the Xyz feature of Foo.
 +
}
 +
 +
}  // namespace
 +
 +
int main(int argc, char **argv) {
 +
  ::testing::InitGoogleTest(&argc, argv);
 +
  return RUN_ALL_TESTS();
 +
}
 +
</syntaxhighlight>
 +
  
 
== ヘッダファイル ==
 
== ヘッダファイル ==
  
 
<syntaxhighlight lang="cpp">
 
<syntaxhighlight lang="cpp">
 +
/usr/local/include/gtest/gtest-death-test.h
 +
/usr/local/include/gtest/gtest-message.h
 +
/usr/local/include/gtest/gtest-param-test.h
 +
/usr/local/include/gtest/gtest-spi.h
 +
/usr/local/include/gtest/gtest-test-part.h
 +
/usr/local/include/gtest/gtest-typed-test.h
 +
/usr/local/include/gtest/gtest.h
 +
/usr/local/include/gtest/gtest_pred_impl.h
 +
/usr/local/include/gtest/gtest_prod.h
 +
/usr/local/include/gtest/internal/gtest-death-test-internal.h
 +
/usr/local/include/gtest/internal/gtest-filepath.h
 +
/usr/local/include/gtest/internal/gtest-internal.h
 +
/usr/local/include/gtest/internal/gtest-linked_ptr.h
 +
/usr/local/include/gtest/internal/gtest-param-util-generated.h
 +
/usr/local/include/gtest/internal/gtest-param-util.h
 +
/usr/local/include/gtest/internal/gtest-port.h
 +
/usr/local/include/gtest/internal/gtest-string.h
 +
/usr/local/include/gtest/internal/gtest-tuple.h
 +
/usr/local/include/gtest/internal/gtest-type-util.h
 +
</syntaxhighlight>
  
 +
 +
== 実行例 ==
 +
 +
<syntaxhighlight lang="bash">
 +
g++ $(gtest-config --cppflags --cxxflags) -o foo.o -c foo.cpp
 +
g++ $(gtest-config --ldflags --libs) -o foo foo.o
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== ソースコード ==
+
== サンプルコード ==
 +
 
 +
=== ソースコード foo.hpp ===
 +
 
 +
プログラムの実装です。
  
 
<syntaxhighlight lang="cpp">
 
<syntaxhighlight lang="cpp">
 +
#ifndef FOO_HPP
 +
#define FOO_HPP
  
 +
#include <exception>
 +
#include <string>
 +
 +
class foo {
 +
        public:
 +
                int add(int a, int b) {
 +
                        return a+b;
 +
                }
 +
 +
                void throw_exception () throw(std::exception) {
 +
                        throw std::exception ();
 +
                }
 +
 +
                void no_throw_exception () {
 +
                        ;
 +
                }
 +
 +
                std::string get_str_foo () throw () {
 +
                        return std::string("foo");
 +
                }
 +
 +
                bool is_true () {
 +
                        return true;
 +
                }
 +
 +
                bool is_false () {
 +
                        return false;
 +
                }
 +
 +
};
 +
#endif // FOO_HPP
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
=== ソースコード gtest_main.cpp ===
  
 +
テストプログラムのメイン関数です。
 +
<syntaxhighlight lang="cpp">
 +
#include <gtest/gtest.h>
  
== 実行例 ==
+
int
 +
main(int argc, char *argv[])
 +
{
 +
        ::testing::InitGoogleTest(&argc, argv);
 +
        return RUN_ALL_TESTS();
 +
}
 +
</syntaxhighlight>
 +
 
 +
=== ソースコード fooTest.cpp ===
 +
 
 +
テストコードの実体です。
 +
gtest_main.cpp とわけなくても構いません。
 +
 
 +
<syntaxhighlight lang="cpp">
 +
#include <gtest/gtest.h>
 +
 
 +
#include "foo.hpp"
 +
 
 +
TEST(foo, add) {
 +
        foo f;
 +
        ASSERT_EQ(3, f.add(1,2));
 +
        ASSERT_EQ(4, f.add(2,2));
 +
}
 +
 
 +
TEST(foo, get_str_foo) {
 +
        foo f;
 +
        ASSERT_EQ("foo", f.get_str_foo());
 +
}
 +
 
 +
TEST(foo, is) {
 +
        foo f;
 +
        ASSERT_TRUE(f.is_true ());
 +
        //ASSERT_FALSE(f.is_true ());
 +
        ASSERT_FALSE(f.is_false ());
 +
}
 +
 
 +
TEST(foo, exception) {
 +
        foo f;
 +
        ASSERT_THROW(f.throw_exception(), std::exception);
 +
        ASSERT_NO_THROW(f.no_throw_exception());
 +
}
 +
</syntaxhighlight>
 +
 
 +
=== コンパイル ===
  
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
 +
g++ `gtest-config --ldflags --libs `  -I`gtest-config --includedir`gtest_main.cpp fooTest.cpp
 +
 +
# sh系ならこれでもよい。
 +
g++ $(gtest-config --ldflags --libs ) -I$(gtest-config --includedir) gtest_main.cpp fooTest.cpp
 +
</syntaxhighlight>
 +
 +
=== 実行例 ===
 +
 +
すべてのテストが成功する例です。
 +
 +
<syntaxhighlight lang="bash">
 +
./a.out
 +
[==========] Running 4 tests from 1 test case.
 +
[----------] Global test environment set-up.
 +
[----------] 4 tests from foo
 +
[ RUN      ] foo.add
 +
[      OK ] foo.add (0 ms)
 +
[ RUN      ] foo.get_str_foo
 +
[      OK ] foo.get_str_foo (0 ms)
 +
[ RUN      ] foo.is
 +
[      OK ] foo.is (0 ms)
 +
[ RUN      ] foo.exception
 +
[      OK ] foo.exception (1 ms)
 +
[----------] 4 tests from foo (1 ms total)
 +
 +
[----------] Global test environment tear-down
 +
[==========] 4 tests from 1 test case ran. (2 ms total)
 +
[  PASSED  ] 4 tests.
 +
</syntaxhighlight>
 +
 +
is_true() を失敗させた例です。
 +
<syntaxhighlight lang="bash">
 +
[==========] Running 4 tests from 1 test case.
 +
[----------] Global test environment set-up.
 +
[----------] 4 tests from foo
 +
[ RUN      ] foo.add
 +
[      OK ] foo.add (0 ms)
 +
[ RUN      ] foo.get_str_foo
 +
[      OK ] foo.get_str_foo (0 ms)
 +
[ RUN      ] foo.is
 +
fooTest.cpp:19: Failure
 +
Value of: f.is_true ()
 +
  Actual: true
 +
Expected: false
 +
[  FAILED  ] foo.is (1 ms)
 +
[ RUN      ] foo.exception
 +
[      OK ] foo.exception (2 ms)
 +
[----------] 4 tests from foo (4 ms total)
 +
 +
[----------] Global test environment tear-down
 +
[==========] 4 tests from 1 test case ran. (4 ms total)
 +
[  PASSED  ] 3 tests.
 +
[  FAILED  ] 1 test, listed below:
 +
[  FAILED  ] foo.is
  
 +
1 FAILED TEST
 
</syntaxhighlight>
 
</syntaxhighlight>
  
行58: 行369:
  
 
* [[ユニットテストフレームワーク]]
 
* [[ユニットテストフレームワーク]]
 +
* [[gtest-config]]

2013年3月9日 (土) 15:52時点における最新版


Google Test は、 C++ 向けのユニットテストフレームワークです。

読み方

Google Test
ぐーぐる てすと

概要

Google C++ Testing Framework です。

赤と緑のカラー表示で、コンソールでも賑やかでステキです。

インストール

FreeBSDにインストールする場合

ports コレクションからインストールする場合

cd /usr/ports/devel/googletest
sudo make install clean

pkgコマンドでインストールする場合

sudo pkg install googletest

portmasterコマンドでインストールする場合

sudo portmaster -y -d /usr/ports/devel/googletest

ソースからビルド

svn checkout http://googletest.googlecode.com/svn/trunk/ googletest-read-only
cd googletest-read-only
cmake .
gmake

./libgtest.a ./libgtest_main.a

が作成されます。

アサーション

Google Test のアサーションは、マクロです。動作を調べるために、アサーションを利用します。

ASSERT_* バージョンが失敗した場合は、致命的な失敗となり、実行中の関数を中断します。 EXPECT_* バージョンが失敗した場合は、致命的ではない失敗となり、関数を中断しません。

基本的なアサーション

基本的なアサーション
致命的なアサーション 致命的ではないアサーション 検証内容
ASSERT_TRUE(condition); EXPECT_TRUE(condition); condition が true
ASSERT_FALSE(condition); EXPECT_FALSE(condition); condition が false

2つの値の比較

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

文字列の比較

文字列の比較
致命的なアサーション 致命的ではないアサーション 検証内容
ASSERT_STREQ(expected_str, actual_str); EXPECT_STREQ(expected_str, actual_str); 2つの C 文字列の内容が等しい
ASSERT_STRNE(str1, str2); EXPECT_STRNE(str1, str2); 2つの C 文字列の内容が等しくない
ASSERT_STRCASEEQ(expected_str, actual_str); EXPECT_STRCASEEQ(expected_str, actual_str); 大文字小文字を無視した場合,2つの C 文字列の内容が等しい
ASSERT_STRCASENE(str1, str2); EXPECT_STRCASENE(str1, str2); 大文字小文字を無視した場合,2つの C 文字列の内容が等しくない

main()関数を書く

#include "this/package/foo.h"
#include "gtest/gtest.h"
 
namespace {
 
// The fixture for testing class Foo.
class FooTest : public ::testing::Test {
 protected:
  // You can remove any or all of the following functions if its body
  // is empty.
 
  FooTest() {
    // You can do set-up work for each test here.
  }
 
  virtual ~FooTest() {
    // You can do clean-up work that doesn't throw exceptions here.
  }
 
  // If the constructor and destructor are not enough for setting up
  // and cleaning up each test, you can define the following methods:
 
  virtual void SetUp() {
    // Code here will be called immediately after the constructor (right
    // before each test).
  }
 
  virtual void TearDown() {
    // Code here will be called immediately after each test (right
    // before the destructor).
  }
 
  // Objects declared here can be used by all tests in the test case for Foo.
};
 
// Tests that the Foo::Bar() method does Abc.
TEST_F(FooTest, MethodBarDoesAbc) {
  const string input_filepath = "this/package/testdata/myinputfile.dat";
  const string output_filepath = "this/package/testdata/myoutputfile.dat";
  Foo f;
  EXPECT_EQ(0, f.Bar(input_filepath, output_filepath));
}
 
// Tests that Foo does Xyz.
TEST_F(FooTest, DoesXyz) {
  // Exercises the Xyz feature of Foo.
}
 
}  // namespace
 
int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}


ヘッダファイル

/usr/local/include/gtest/gtest-death-test.h
/usr/local/include/gtest/gtest-message.h
/usr/local/include/gtest/gtest-param-test.h
/usr/local/include/gtest/gtest-spi.h
/usr/local/include/gtest/gtest-test-part.h
/usr/local/include/gtest/gtest-typed-test.h
/usr/local/include/gtest/gtest.h
/usr/local/include/gtest/gtest_pred_impl.h
/usr/local/include/gtest/gtest_prod.h
/usr/local/include/gtest/internal/gtest-death-test-internal.h
/usr/local/include/gtest/internal/gtest-filepath.h
/usr/local/include/gtest/internal/gtest-internal.h
/usr/local/include/gtest/internal/gtest-linked_ptr.h
/usr/local/include/gtest/internal/gtest-param-util-generated.h
/usr/local/include/gtest/internal/gtest-param-util.h
/usr/local/include/gtest/internal/gtest-port.h
/usr/local/include/gtest/internal/gtest-string.h
/usr/local/include/gtest/internal/gtest-tuple.h
/usr/local/include/gtest/internal/gtest-type-util.h


実行例

g++ $(gtest-config --cppflags --cxxflags) -o foo.o -c foo.cpp
g++ $(gtest-config --ldflags --libs) -o foo foo.o

サンプルコード

ソースコード foo.hpp

プログラムの実装です。

#ifndef FOO_HPP
#define FOO_HPP
 
#include <exception>
#include <string>
 
class foo {
        public:
                int add(int a, int b) {
                        return a+b;
                }
 
                void throw_exception () throw(std::exception) {
                        throw std::exception ();
                }
 
                void no_throw_exception () {
                        ;
                }
 
                std::string get_str_foo () throw () {
                        return std::string("foo");
                }
 
                bool is_true () {
                        return true;
                }
 
                bool is_false () {
                        return false;
                }
 
};
#endif // FOO_HPP

ソースコード gtest_main.cpp

テストプログラムのメイン関数です。

#include <gtest/gtest.h>
 
int
main(int argc, char *argv[])
{
        ::testing::InitGoogleTest(&argc, argv);
        return RUN_ALL_TESTS();
}

ソースコード fooTest.cpp

テストコードの実体です。 gtest_main.cpp とわけなくても構いません。

#include <gtest/gtest.h>
 
#include "foo.hpp"
 
TEST(foo, add) {
        foo f;
        ASSERT_EQ(3, f.add(1,2));
        ASSERT_EQ(4, f.add(2,2));
}
 
TEST(foo, get_str_foo) {
        foo f;
        ASSERT_EQ("foo", f.get_str_foo());
}
 
TEST(foo, is) {
        foo f;
        ASSERT_TRUE(f.is_true ());
        //ASSERT_FALSE(f.is_true ());
        ASSERT_FALSE(f.is_false ());
}
 
TEST(foo, exception) {
        foo f;
        ASSERT_THROW(f.throw_exception(), std::exception);
        ASSERT_NO_THROW(f.no_throw_exception());
}

コンパイル

g++ `gtest-config --ldflags --libs `  -I`gtest-config --includedir`gtest_main.cpp fooTest.cpp
 
# sh系ならこれでもよい。
g++ $(gtest-config --ldflags --libs ) -I$(gtest-config --includedir) gtest_main.cpp fooTest.cpp

実行例

すべてのテストが成功する例です。

./a.out
[==========] Running 4 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 4 tests from foo
[ RUN      ] foo.add
[       OK ] foo.add (0 ms)
[ RUN      ] foo.get_str_foo
[       OK ] foo.get_str_foo (0 ms)
[ RUN      ] foo.is
[       OK ] foo.is (0 ms)
[ RUN      ] foo.exception
[       OK ] foo.exception (1 ms)
[----------] 4 tests from foo (1 ms total)
 
[----------] Global test environment tear-down
[==========] 4 tests from 1 test case ran. (2 ms total)
[  PASSED  ] 4 tests.

is_true() を失敗させた例です。

[==========] Running 4 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 4 tests from foo
[ RUN      ] foo.add
[       OK ] foo.add (0 ms)
[ RUN      ] foo.get_str_foo
[       OK ] foo.get_str_foo (0 ms)
[ RUN      ] foo.is
fooTest.cpp:19: Failure
Value of: f.is_true ()
  Actual: true
Expected: false
[  FAILED  ] foo.is (1 ms)
[ RUN      ] foo.exception
[       OK ] foo.exception (2 ms)
[----------] 4 tests from foo (4 ms total)
 
[----------] Global test environment tear-down
[==========] 4 tests from 1 test case ran. (4 ms total)
[  PASSED  ] 3 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] foo.is
 
 1 FAILED TEST

関連項目