Boost logo

Boostテストライブラリ: テスト実行モニター

ホーム
イントロダクション
メリット
サンプル
コンパイル
テスト・サンプルプログラム
理論
設計

関連事項: ユニットテストフレームワーク

イントロダクション

Boostテストライブラリのテスト実行モニターはmain()関数を提供し、その中でユーザの作成したtest_main() 関数を呼び出す。ライブラリの提供するmain()関数によって、ユーザは面倒なエラー検出・報告作業から解放される。テスト実行モニター は、極めてシンプルなテストプログラムや既存の製品コード内の不具合を見つけ出す際の使用を意図している。 (非テスト用の)製品プログラムをモニタするのには、プログラム実行モニター の方が適している。 複雑なテストプログラム にはユニットテストフレームワーク が適している。

メリット

テスト実行モニターはプログラムテストの簡単な枠組を提供する。reference to the top

サンプル

この例では、add()関数に対するエラーの検知・報告の6つの異なる方法を示している。

#include <boost/test/test_tools.hpp>

int add( int i, int j ) { return i+j; }

int test_main( int, char *[] )             // 名前に注目!
{
    // 同じエラーを6通りの方法で検出:
    BOOST_CHECK( add( 2,2 ) == 4 );        // #1 エラーが起きても継続する
    BOOST_REQUIRE( add( 2,2 ) == 4 );      // #2 エラーの際に例外を発生する
    if( add( 2,2 ) != 4 )
      BOOST_ERROR( "Ouch..." );            // #3 エラーが起きても継続する
    if( add( 2,2 ) != 4 )
      BOOST_FAIL( "Ouch..." );             // #4 エラーの際に例外を発生する
    if( add( 2,2 ) != 4 ) throw "Oops..."; // #5 エラーの際に例外を発生する

    return add( 2, 2 ) == 4 ? 0 : 1;       // #6 エラーコードを返す
}

Approach #1 BOOST_CHECK を使うと、失敗した旨、ソースファイル名、行番号を含むエラーメッセージをstd::coutに出力する。また、エラーカウントをインクリメントし、プログラム終了時にエラーカウントがテスト実行モニターによって自動的に表示される。

Approach #2 BOOST_REQUIRE は#1と似ているが, エラーを出力した後で例外を発生し、 それをテスト実行モニターがキャッチする点が異なる。 このアプローチは明確なテストプログラムを書くにあたり、発生したエラーが深刻でなものでこれ以上テストを継続できないようなときに適している。 BOOST_REQUIRE は、C++標準ライブラリのマクロと異なり常に生成されており、検知したエラーをテスト実行モニター に統一形式で報告する処理に繋げる。

Approaches #3 and #4 はそれぞれ#1 and #2 に似ているが、エラー検出コードを別に記述する。これはテストを行う条件から、失敗の理由がはっきりわからない場合に便利である。

Approach #5 例外を発生し、それがテスト実行モニターによってキャッチされる。このアプローチは、ライブラリ内にあるなしにかかわらず、製品とテストコードの両方に適している。例外をキャッチした際に表示されるエラーメッセージは、その例外がstd::exceptionから派生している場合、またはchar*、std::stringである場合に最も重要である。

Approach #6 は呼び出し側にエラーを通知するのに返り値を使用する。 このアプローチは特に、テストツールライブラリを使った既存のテストコードを統合する際に適している。これはBoostプログラム実行モニターまたは テスト実行モニター ライブラリでも十分動作し、それらの元で既存のコードを実行するのに非常に便利であるが、多くのC++に熟達した人達はエラー報告に例外を使用するのを好む。 reference to the top

テスト実行モニターのコンパイル

テスト実行モニター は個別のライブラリとして提供されているので、コンパイル後にテストプログラムとリンクする必要がある。Boostテストライブラリのソースディレクトリに配置されている以下のファイルによりこのコンポーネントは構成されている。

execution_monitor.cpp
test_tools.cpp
unit_test_log.cpp
unit_test_parameters.cpp
unit_test_monitor.cpp
unit_test_result.cpp
unit_test_suite.cpp
test_main.cpp

テスト実行モニターを構成するファイルをすべて、作成するテストモジュールに取り込むことも可能である。その際には<boost/test/included/test_exec_monitor.hpp> を使う。

サンプル・テストプログラム

test_exec_example
test_exec_fail1
test_exec_fail2
test_exec_fail3
test_exec_fail4

reference to the top

理論

テストプログラムはどのようにしてエラーを報告するのがよいか。わかりやすいのがエラーメッセージを表示することである。

if( something_bad_detected )
  std::cout << "何か良くないものが検出された" << std::endl;

これだと実行する毎に出力内容を検査し、エラーが起きたかどうかを判断しなければならない。テストプログラムは回帰テストとして何度も実行されるものなので、人間が出力を見てエラーを検出するのは時間がかかり過ぎるし信頼性に欠ける。これに対しGNU/expectのようなテストフレームワークは、エラーの検出を自動的に行うことができるが、簡単なテストを行う際には手間がかかり過ぎる。

エラーを報告するより簡単な方法は、テストプログラムが満足いくように終了した場合EXIT_SUCCESS(通常0)を返す、エラーを検出した場合EXIT _FAILUREを返すことである。これだと簡単な回帰テストスクリプトで、曖昧さのない自動エラー検出を行うことができる。HTMLテーブルの作成やメールによる警告の通知などのより適切な処理をスクリプトによって実現でき、実際のC++テストプログラムを変更せずに思い通りの修正を行うことができる。

テストプログラムがEXIT_SUCCESSまたはEXIT_FAILUREを返すという考えを基にしたテストルールは、いかなる支援ツールも必要としない。つまり、C++ 言語と標準ライブラリで充分なのである。また一方で、プログラマが覚えておかなければならないのが、すべての例外を漏らさずキャッチし、非ゼロ値を返してプログラムを終了させなければならないということである。それに、テストコード向けに標準ライブラリのassert()マクロも使ってはならない。システムによっては、手動での操作が必要になるなど、望ましくない副作用を伴うからである。

テスト実行モニターはこれらのタスクを自動化してくれるが、プログラマはそれを無視して0を返り値とするテストを作成しがちである。

設計

The Boostテストライブラリ設計 ドキュメントはBoostテストライブラリコンポーネント間の関係を記述している。 reference to the top