ユニットテストを作成するための特定のツールに着手する前に、ユニット(またはユニット)テストとは何か、その基本原則、および一般に、このビジネスに個別のライブラリが必要な理由を判断しましょう。
したがって、この原則は、プログラムのソースコードの重要な関数またはメソッドごとに小さなテストを作成することです。 このアプローチは何をもたらしますか? まず、このようなテストを実施した後、すべての部品が個別に機能していると明確に言うことができます(「ミッシングエラー」の概念と混同しないでください)。 第二に、回帰テストを実施できます。 そして第三に、単体テストは、テストされた関数とクラスの使用方法の良い例です。 単体テスト-間接的な文書化の手段。
また、私の意見では、単体テストの原則についても触れたいと思います。 それらをリストします。
- テストは小さくて高速でなければなりません。
- テストは自動でなければなりません。
- テストは相互に依存したり、シーケンスの順序に依存したりしないでください。
- 最初に、ブラックボックスモードでテストを記述します。
- そして、「ホワイト」モードで。
- 間違いを見つけた-それを再現するテストを書く正当な理由。
- テストの構造は、プロジェクトの階層を繰り返す必要があります。
- クラスごとに、個別のテストクラスを用意します。
- メインプロジェクトからテストを分離します。
- テストに名前を付けるための統一されたシステムがあります(たとえば、MyClassクラスの場合、テストクラスの名前はMyClassTestになり、そのメソッドはすべてtestWhatTest()の形式になります)。
そのため、さまざまなルーチン操作(main()サポート、クラスインスタンスの作成、メッセージの表示など)を自動化するツールが必要です。 いくつかの要件を提示します。
- このツールは、起動、保守、および学習が簡単でなければなりません。
- 強力でなければなりません。
- クロスプラットフォームでなければなりません。
- ツールがテストを構築するための特定のフレームワークを定義していると便利です。
現時点では、C ++で単体テストを作成するためのライブラリ(膨大な数の9000以上)があります。 ここに皆のために彼らの好みに手段があります。 それらのいくつかを簡単にリストします。
Boost ::テスト
BoostはC ++で最も有名な(そして大きな)ライブラリの1つであり、Boost :: Testはそれに含まれており、マクロ上に構築されたテストフレームワークです。
Boostの最初の知り合いはあまり良い思い出を残しませんでした-ドキュメントがかさばり、扱いにくいです。さらに、このモンスターはかなりの重量があります(はい、ライブラリ全体をプロジェクトにアタッチする必要はありません。Boost:: Testを使用できますが、ダウンロードできます完全にある必要があります)。
ドキュメントから小さなテスト例を示します:
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
Copy Source | Copy HTML #include <boost/test/minimal.hpp> Int add( int i, int j ) { return i+j; } Int test_main( int , char *[ ] ) // note the name! { BOOST_CHECK( add( 2 , 2 ) == 4 ); // #1 continues on error BOOST_REQUIRE( add( 2 , 2 ) == 4 ); // #2 throws on error if ( add( 2 , 2 ) != 4 ) BOOST_ERROR( "Ouch..." ); // #3 continues on error if ( add( 2 , 2 ) != 4 ) BOOST_FAIL( "Ouch..." ); // #4 throws on error if ( add( 2 , 2 ) != 4 ) throw "Oops..." ; // #5 throws on error return add( 2 , 2 ) == 4 ? 0 : 1 ; // #6 returns error code }
QTestLib
また、それほど有名ではないライブラリですが、レビューによるとかなり複雑であり、テストのためにすべてのQTをプルすることは正当化されません。
UnitTest ++
悪くて人気のあるものではありませんが、ドキュメントは貧弱です。
そして最後に:
Cxxtest
私の意見では、単体テストを書くための最高のxUnitライクなライブラリの1つです。
機能の:
- ソースコードに何も埋め込む必要はありません
- インストールは必要ありません(「テスト」ブランチでプロジェクトに簡単に統合できます)
- サードパーティのライブラリをプルしません
- 私の意見では、最高のマニュアルの1つがあります。 トレーニングは単純なものから複雑なものへと変化します(さまざまな例と写真を使用します;))。
欠点の:
- PerlまたはPythonが必要です。 実際、Linuxにはデフォルトで両方ありますが、Windows Pythonの場合は優れたユーティリティツールとして使用します。
それでは、CxxTestの使用方法を見てみましょう。
- * .hファイルを作成する
- CxxTestから継承したクラスを作成する:: TestSuite
- testMethod(void)メソッドを実装します(重要:最初の単語は必ずテストする必要があります-そうでない場合、システムはそれをテストとして認識しません)
Copy Source | Copy HTML
- クラス MyTest : public CxxTest :: TestSuite
- {
- 公開 :
- void testMethod( void )
- {
- TS_ASSERT( 1 + 1 > 1 );
- TS_ASSERT_EQUALS( 1 + 1、2 );
- }
- };
- プリプロセッサを実行する
Copy Source | Copy HTML
- #perl cxxtestgen.pl --error-printer -o runner.cpp MyTest.h
- MyTest.h-私たちが書いたテスト
- runner.cpp-出力ファイル(メイン()関数がその中に作成されます)
- cxxtestgen.plまたはcxxtestgen.py-プリプロセッサ
- ...そしてコンパイル
Copy Source | Copy HTML
- #g ++ -o runner runner.cpp
成功した場合、次の形式の式を取得します。
Copy Source | Copy HTML
- #./runner
- 1つのテストを実行します。OK!
さて、ソースコードに何か正しくない場合、CxxTestは丁寧に指示します。
Copy Source | Copy HTML
- #./runner
- 2つのテストを実行します。
- MyTest.h:15:期待(2 * 2 == 5)、 見つかった (4!= 5)
- 2つのテストのうち1つに失敗しました
- 成功率:50%
まとめると。
CxxTestは、C ++で単体テストを作成するための非常に便利なフレームワークです。さらに、プログラマの作業を容易にするだけでなく、テストの正しい作成にも貢献します。
CxxTestにリストされている機能に加えて、テストを視覚化するためのシンプルなインターフェイスを(プログレスバーの形で)簡単に作成できます。また、モックオブジェクトもサポートされています。
PS
Inversionの招待に感謝します。