2009年05月26日(火) [長年日記]
- 運動のため、ときどき家まで歩いて帰ってみている。1時間くらいで帰れる。
- 暇は終了している。今はC++を使っています。
■ [c++][dev] Boost Test Library Unit Test Framework のサンプル
Boost Test Libraryに含まれているUnit Test Frameworkを使ったのでサンプルをメモ。
手元のBoostのバージョンは1.37、最新は1.39のようだ。
サンプルソース
test_main.cpp、vector_test1.cpp、vector_test2.cpp の3つのファイルを作った。
- テストの構成は色々あるようだが、dynamic library variant方式にした。BOOST_TEST_DYN_LINK を define すればいいみたい。
- dynamic library variant方式の場合は BOOST_TEST_MODULE を define すると main() が自動生成される。
- include するヘッダは boost/test/unit_test.hpp。
- テストケースは BOOST_AUTO_TEST_CASE() を使って書くのがよさそう。
- 値の検査は BOOST_CHECK_EQUAL() や BOOST_REQUIRE_EQUAL() で行える。BOOST_CHECK_EQUAL() だと検査がfailedになった場合でもテストケースの処理は先へ進む。使える検査用のマクロ一覧はリファレンスにある。
- setup, teardown 相当の処理は、「フィクスチャ」のコンストラクタとデストラクタで行う。下のサンプルではフィクスチャとして Fixture というクラスを作った。
- テストケース内ではフィクスチャクラスのメンバ変数に直接アクセスできる。フィクスチャクラスを継承しているようだ。
- フィクスチャを使うときは、Test suite level fixtureを使用するのがよさそう。BOOST_FIXTURE_TEST_SUITE() を使う。
- テストケースやフィクスチャは無名(じゃなくてもいいけど)名前空間の中に書くのがよさそう。名前の衝突を気にしなくてよくなるので。
- 全体的に文字列をほとんど与えられず、日本語を埋め込む余地があまりなさそうなのが残念。
// test_main.cpp #define BOOST_TEST_MODULE "ここは日本語を書けそう" #define BOOST_TEST_DYN_LINK #include <boost/test/unit_test.hpp>
// vector_test1.cpp
#include <boost/test/unit_test.hpp>
#include <vector>
namespace {
struct Fixture {
std::vector<int> v;
Fixture() {
v.push_back(1);
}
};
BOOST_FIXTURE_TEST_SUITE(my_suite, Fixture)
BOOST_AUTO_TEST_CASE(add_element) {
// Fixtureのメンバ変数 v を直接参照できる
v.push_back(100);
BOOST_CHECK_EQUAL(v.back(), 100);
BOOST_CHECK_EQUAL(v.size(), 2);
}
BOOST_AUTO_TEST_CASE(remove_element) {
v.pop_back();
BOOST_CHECK_EQUAL(v.size(), 0);
}
BOOST_AUTO_TEST_SUITE_END()
}
// vector_test2.cpp
#include <boost/test/unit_test.hpp>
#include <vector>
namespace {
struct Fixture {
std::vector<int> v;
Fixture() {
v.push_back(1);
v.push_back(2);
v.push_back(3);
}
};
BOOST_FIXTURE_TEST_SUITE(my_suite, Fixture)
BOOST_AUTO_TEST_CASE(add_element) {
v.push_back(100);
BOOST_CHECK_EQUAL(v.back(), 100);
BOOST_CHECK_EQUAL(v.size(), 4);
}
BOOST_AUTO_TEST_CASE(remove_element) {
v.pop_back();
BOOST_CHECK_EQUAL(v.back(), 2);
// テストをわざと失敗させるてみる
BOOST_CHECK_EQUAL(v.size(), 100);
BOOST_REQUIRE_EQUAL(v.empty(), true); // これも実行される
BOOST_CHECK_EQUAL(v[0], 100); // これは実行されない
}
BOOST_AUTO_TEST_SUITE_END()
}
ビルド
次のようにしてビルドできる。
$ g++ -Wall -lboost_unit_test_framework-mt -o testrunner *.cpp
実行結果
実行結果は次の通り。
$ ./testrunner Running 4 test cases... vector_test2.cpp(29): error in "remove_element": check v.size() == 100 failed [2 != 100] vector_test2.cpp(30): fatal error in "remove_element": critical check v.empty() == true failed [false != true] *** 2 failures detected in test suite "ここは日本語を書けそう"
オプションを付けることで出力内容を変えられるが、気に入ったフォーマットが見当たらない。
$ ./testrunner --log_level=test_suite --report_level=detailed
Running 4 test cases...
Entering test suite "ここは日本語を書けそう"
Entering test suite "my_suite"
Entering test case "add_element"
Leaving test case "add_element"
Entering test case "remove_element"
vector_test2.cpp(29): error in "remove_element": check v.size() == 100 failed [2 != 100]
vector_test2.cpp(30): fatal error in "remove_element": critical check v.empty() == true failed [false != true]
Leaving test case "remove_element"
Entering test case "add_element"
Leaving test case "add_element"
Entering test case "remove_element"
Leaving test case "remove_element"
Leaving test suite "my_suite"
Leaving test suite "ここは日本語を書けそう"
Test suite "ここは日本語を書けそう" failed with:
6 assertions out of 8 passed
2 assertions out of 8 failed
3 test cases out of 4 passed
1 test case out of 4 failed
1 test case out of 4 aborted
Test suite "my_suite" failed with:
6 assertions out of 8 passed
2 assertions out of 8 failed
3 test cases out of 4 passed
1 test case out of 4 failed
1 test case out of 4 aborted
Test case "add_element" passed with:
2 assertions out of 2 passed
Test case "remove_element" aborted with:
1 assertion out of 3 passed
2 assertions out of 3 failed
Test case "add_element" passed with:
2 assertions out of 2 passed
Test case "remove_element" passed with:
1 assertion out of 1 passed
■ やること
- 請求書
- 請書
[ツッコミを入れる]