ある関数をテストする時に、パラメータが 1の時、2の時、3の時… についてテストしたい、という場合に、

BOOST_TEST_CASE(hoge_test)
{
    BOOST_CHECK(hoge(1) == 0);
    BOOST_CHECK(hoge(2) == 0);
    BOOST_CHECK(hoge(3) == 0);
}

と書く代わりに

using namespace boost::unit_test;
int param[] = { 1, 2, 3 };
BOOST_DATA_TEST_CASE(hoge_test, data::make(param), i)
{
    BOOST_CHECK(hoge(i) == 0);
}

と書くことができます。(Boost 1.59.0 以降。それより前だと面倒な異なる書き方をする)

この例だとあまりご利益がありませんが、同じパラメータの列を別のテストでも使いまわしたいとか、途中に BOOST_REQUIRE がある(失敗するとテストケースがそこで終了してしまう)場合とか考え始めると利点が生じます。

boost::unit_test::data::make から返ってくるオブジェクトを dataset と呼ぶのですが、 dataset 同士の演算ができて、

using namespace boost::unit_test;
int param1[] = { 1, 2, 3 };
int param2[] = { 4, 5 };
BOOST_DATA_TEST_CASE(fuga_test, data::make(param1) * data::make(param2), i, j)
{
    BOOST_CHECK(fuga(i, j) == 0);
}

とか書くと、{ i, j } = { 1, 4 }, { 1, 5 }, { 2, 4 }, { 2, 5 }, { 3, 4 }, { 3, 5 } のテストが一気に行えます。

ここまで前置き。

この機能、便利なんですが、ちょっと残念なところもあります(以下、boost 1.60.0 時点の話)

まずパラメータの数(arity という)が3までです。つまり、以下はコンパイルエラーになります。

using namespace boost::unit_test;
int param1[] = { 1, 2, 3 };
int param2[] = { 4, 5 };
int param3[] = { 6, 7 };
int param4[] = { 8, 9 };
BOOST_DATA_TEST_CASE(fuga_test, data::make(param1) * data::make(param2) * data::make(param3) * data::make(param4), i, j, k, l)
{
    /* XXX */
}

以下は arity が 3 なのでセーフです。

using namespace boost::unit_test;
int param1[] = { 1, 2, 3 };
int param2[] = { 4, 5 };
int param3[] = { 6, 7 };
BOOST_DATA_TEST_CASE(fuga_test, data::make(param1) * data::make(param2) * data::make(param3), i, j, k)
{
    /* XXX */
}

また、標準的に提供されないような dataset の操作をしようとすると、すごい難しいことになります。data::make の返り値の型は「同じインターフェースを実装したクラス」ではなく「テンプレートで同じように操作できるクラス」(たとえば vector<int>list<int> は派生関係は無いが beginend などが実装されているので同じように操作できる)であるため、これを操作するような処理を書こうとするとこれまたテンプレートのお世話になります。

実際に、{ 1, { a, b } }, { 2, { c, d } } という dataset を { 1, a }, { 1, b }, { 2, c }, { 2, d } に展開するような(汎用的な)処理を書きたかったのですが、テンプレートの闇に阻まれ実現できませんでした。C++ 難しいよ。

arity が 3 までな点は boost のソースを読むと将来何とかしたいみたいなコメントがあるので期待できます。dataset の操作の方は boost 側が何とかしてくれることは考えづらく、自分で何とかするにはテンプレートに対する深い理解が必要そうで、すぐにはできそうにありません。

Trackback

only 1 comment untill now

  1. Boost C++ libraries 1.61.0 がリリースされてた

    1.61.0 がリリースされてました。 now datasets support any arity, using the variadic template support of the compiler. http://www.boost.org/doc/libs/1_61_0/libs/test/doc/html/boost_test/change_log.html やったー!(参考) さっそく…

Add your comment now