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
■ やること
- 請求書
- 請書