この記事は C++ Advent Calendar 2013 の 8 日目の記事になります(あれ、俺 8 日目なのか……)。このネタを思いついたのは、先月に boostjp の ML で見かけた以下の投稿からでした。
Boost 1.55.0 Beta 1 RCが公開されました。
https://groups.google.com/forum/#!topic/boostjp/Xub5TE3VCPM
http://lists.boost.org/Archives/boost/2013/10/206792.php
来週頭にはBoost 1.55.0 Beta 1がリリース、今月末のBoost 1.55.0 RCを経て、11月第1週にはBoost 1.55.0のリリースとなるかと思います。
# ちなみにそういったスケジュールは http://www.boost.org/community/ のカレンダーに書いてあります。
1.55.0リリースしてから問題があっても遅いので、今のうちからテストしたりしてもらえると非常に助かります。
この投稿を見ながら(投稿内容とはちょっとずれていますが)「あぁ、バージョンアップの度に、サンプルコードがきちんと動作をするかどうかもテストした方が良いのか」と思い、「Boost 逆引きリファレンスのサンプルコード、テスト化計画」を密かに始めてみました。
clown/boostjp では、Boost 逆引きリファレンス に掲載されている各種サンプルコードを出来るだけ原型を保ったままテスト化すると言う試みを行っています。例えば、配列 - boostjp の最初のサンプルコード
#include <iostream> #include <boost/array.hpp> #include <algorithm> void disp(int x) { std::cout << x << ' '; } int main() { boost::array<int, 3> ar = {3, 1, 4}; std::for_each(ar.begin(), ar.end(), disp); }
これを以下のようにテスト化します。
#include <boost/test/unit_test.hpp> #include <boost/array.hpp> #include <algorithm> #include <sstream> #include "ostream_proxy.h" BOOST_AUTO_TEST_CASE(test_overview) { boost::array<int, 3> ar = { 3, 1, 4 }; std::ostringstream ss; std::for_each(ar.begin(), ar.end(), ostream_proxy(ss)); BOOST_CHECK_EQUAL(ss.str(), "3 1 4 "); }
「標準出力(std::cout)へ出力」と言うサンプルコードのテスト方法
サンプルコードの特徴として、標準出力(std::cout)に出力して結果を確かめる(掲載する)と言うコードが多くなります。特に、前述した例のように「アルゴリズムで指定した関数の中で std::cout に出力する」と言うサンプルコードの場合、どうやってテスト化すべきか悩んだのですが、最終的には以下のような補助クラスを用いて std::cout の代わりに std::ostringstream に出力させ、最後に出力した文字列で比較すると言う形を取る事にしました。
class ostream_proxy { public: explicit ostream_proxy(std::ostream& stream, char separator = ' ') : stream_(stream), separator_(separator) {} template <class T> void operator()(const T& value) const { stream_ << value << separator_; } }
本当はもう少し完成した状態で記事を書く予定だったのですが、予想以上に手間取ってしまったため現時点でひとまず記事として公開します。static assert(コンパイル時にエラーを発生させるサンプルコード)等いくつかはテスト化できそうにないものもありますが、掲載されているサンプルコードはできるだけを網羅してみようかと思います。
Related Pages
- https://sites.google.com/site/boostjp/tips
- clown/boostjp - GitHub (Boost 逆引きリファレンス用のテスト)