C/C ++の単位テストに対する簡単な1つのヘッダーソリューション。
コードに#include "utest.h" !
現在サポートされているプラットフォームは、Linux、MacOS、Windowsです。
現在のサポートされているコンパイラは、GCC、Clang、MSVCのCl.exe、およびClang-Cl.exeです。
また、TCCで動作しますが、警告があります。TCCコンパイラの最新リリース(バージョン0.9.27)には、Utestが機能する機能がありません。コンストラクター属性拡張機能でパッチされたTCCを使用してください。最近のubuntuおよびdebian linuxディストリビューションは、そのパッチを既に含めてTCCを船に船します。自分でTCCをコンパイルする場合は、トランクバージョンを使用すると、予想どおりに機能します。
Utest.hはいくつかのコマンドラインオプションをサポートしています。
--helpヘルプメッセージを出力するためにヘルプ--filter=<filter> 、テストケースをフィルタリングして実行します(特定の問題のあるテストケースを再実行するのに役立ちます)。--list-testsは、1行に1つのテスト名がリストされます。出力名は--filterに渡すことができます。--output=<output>テスト結果(Jenkins、Travis-CI、およびAppveerがテスト結果を解析できること)でXunit XMLファイルを出力します。--enable-mixed-unitsテストごとの出力が混合ユニット(S/MS/US/NS)を含めることを可能にします。--random-order[=<seed>]テストが実行される順序をランダム化します。オプションの引数が提供されていない場合、ランダム開始シードが使用されます。 Utestは、CおよびC ++でのユニットテストのすべての楽しみを可能にする単一のヘッダーライブラリです。ライブラリは、GoogleのGoogleTestフレームワークと同様の出力を提供するように設計されています。
[==========] Running 1 test cases.
[ RUN ] foo.bar
[ OK ] foo.bar (631ns)
[==========] 1 test cases ran.
[ PASSED ] 1 tests.
1つのCまたはC ++ファイルでは、Macro Utest_mainを呼び出す必要があります。
UTEST_MAIN ()これにより、utest.hに呼び出され、すべてのテストケースをインスタンス化し、ユニットテストフレームワークを実行します。
または、独自のメインを書き、Utest.hに電話をかけたい場合は、代わりに、1つのCまたはC ++ファイルの呼び出しでできます。
UTEST_STATE ();そして、あなたがutest.hフレームワークに電話する準備ができたら:
int main ( int argc , const char * const argv []) {
// do your own thing
return utest_main ( argc , argv );
}実行するテストケースを定義するには、以下を実行できます。
#include "utest.h"
UTEST ( foo , bar ) {
ASSERT_TRUE ( 1 );
}Utest Macroは2つのパラメーターを取ります。1つ目は、テストケースが属するセットで、2つ目はテストの名前です。これにより、テストを便利にグループ化できます。
固定されたテストケースは、複数のテストケースで共有できるインスタンス化された構造体があるものです。
struct MyTestFixture {
char c ;
int i ;
float f ;
};
UTEST_F_SETUP ( MyTestFixture ) {
utest_fixture -> c = 'a' ;
utest_fixture -> i = 42 ;
utest_fixture -> f = 3.14f ;
// we can even assert and expect in setup!
ASSERT_EQ ( 42 , utest_fixture -> i );
EXPECT_TRUE (true);
}
UTEST_F_TEARDOWN ( MyTestFixture ) {
// and also assert and expect in teardown!
ASSERT_EQ ( 13 , utest_fixture -> i );
}
UTEST_F ( MyTestFixture , a ) {
utest_fixture -> i = 13 ;
// teardown will succeed because i is 13...
}
UTEST_F ( MyTestFixture , b ) {
utest_fixture -> i = 83 ;
// teardown will fail because i is not 13!
}上記で示されたいくつかのことに注意してください:
UTEST_F_SETUPとUTEST_F_TEARDOWNマクロが必要です。同じフィクスチャとテストケースを繰り返し使用したい場合もありますが、おそらく1つの変数を微妙に変更します。これは、インデックス付きテストケースが入ってくる場所です。
struct MyTestIndexedFixture {
bool x ;
bool y ;
};
UTEST_I_SETUP ( MyTestIndexedFixture ) {
if ( utest_index < 30 ) {
utest_fixture -> x = utest_index & 1 ;
utest_fixture -> y = ( utest_index + 1 ) & 1 ;
}
}
UTEST_I_TEARDOWN ( MyTestIndexedFixture ) {
EXPECT_LE ( 0 , utest_index );
}
UTEST_I ( MyTestIndexedFixture , a , 2 ) {
ASSERT_TRUE ( utest_fixture -> x | utest_fixture -> y );
}
UTEST_I ( MyTestIndexedFixture , b , 42 ) {
// this will fail when the index is >= 30
ASSERT_TRUE ( utest_fixture -> x | utest_fixture -> y );
}注記:
Googletestが持っているものと一致すると、エラーチェック条件のそれぞれの2つのバリアントが提供されます - 主張して期待しています。アサートが失敗した場合、テストケースは実行を停止し、Utest.hは次のテストケースを継続して実行されます。予想が失敗した場合、テストケースの残りの部分はまだ実行され、さらなるチェックを実行できます。
現在、Utests内で使用する次のマクロを提供しています。
xがtrue(例えばゼロ以外)に評価されると主張します。
UTEST ( foo , bar ) {
int i = 1 ;
ASSERT_TRUE ( i ); // pass!
ASSERT_TRUE ( 42 ); // pass!
ASSERT_TRUE ( 0 ); // fail!
}xがfalse(例えばゼロ)に評価されると主張します。
UTEST ( foo , bar ) {
int i = 0 ;
ASSERT_FALSE ( i ); // pass!
ASSERT_FALSE ( 1 ); // fail!
}xとyは等しいと断言します。
UTEST ( foo , bar ) {
int a = 42 ;
int b = 42 ;
ASSERT_EQ ( a , b ); // pass!
ASSERT_EQ ( a , 42 ); // pass!
ASSERT_EQ ( 42 , b ); // pass!
ASSERT_EQ ( 42 , 42 ); // pass!
ASSERT_EQ ( a , b + 1 ); // fail!
}xとyは等しくないと断言します。
UTEST ( foo , bar ) {
int a = 42 ;
int b = 13 ;
ASSERT_NE ( a , b ); // pass!
ASSERT_NE ( a , 27 ); // pass!
ASSERT_NE ( 69 , b ); // pass!
ASSERT_NE ( 42 , 13 ); // pass!
ASSERT_NE ( a , 42 ); // fail!
}xはy未満であると主張します。
UTEST ( foo , bar ) {
int a = 13 ;
int b = 42 ;
ASSERT_LT ( a , b ); // pass!
ASSERT_LT ( a , 27 ); // pass!
ASSERT_LT ( 27 , b ); // pass!
ASSERT_LT ( 13 , 42 ); // pass!
ASSERT_LT ( b , a ); // fail!
}xはy以下であると主張します。
UTEST ( foo , bar ) {
int a = 13 ;
int b = 42 ;
ASSERT_LE ( a , b ); // pass!
ASSERT_LE ( a , 27 ); // pass!
ASSERT_LE ( a , 13 ); // pass!
ASSERT_LE ( 27 , b ); // pass!
ASSERT_LE ( 42 , b ); // pass!
ASSERT_LE ( 13 , 13 ); // pass!
ASSERT_LE ( 13 , 42 ); // pass!
ASSERT_LE ( b , a ); // fail!
}xはyよりも大きいと主張します。
UTEST ( foo , bar ) {
int a = 42 ;
int b = 13 ;
ASSERT_GT ( a , b ); // pass!
ASSERT_GT ( a , 27 ); // pass!
ASSERT_GT ( 27 , b ); // pass!
ASSERT_GT ( 42 , 13 ); // pass!
ASSERT_GT ( b , a ); // fail!
}xはy以上であると主張します。
UTEST ( foo , bar ) {
int a = 42 ;
int b = 13 ;
ASSERT_GE ( a , b ); // pass!
ASSERT_GE ( a , 27 ); // pass!
ASSERT_GE ( a , 13 ); // pass!
ASSERT_GE ( 27 , b ); // pass!
ASSERT_GE ( 42 , b ); // pass!
ASSERT_GE ( 13 , 13 ); // pass!
ASSERT_GE ( 42 , 13 ); // pass!
ASSERT_GE ( b , a ); // fail!
}文字列xとyは等しいと断言します。
UTEST ( foo , bar ) {
char * a = "foo" ;
char * b = "bar" ;
ASSERT_STREQ ( a , a ); // pass!
ASSERT_STREQ ( b , b ); // pass!
ASSERT_STREQ ( a , b ); // fail!
}文字列xとyは等しくないと断言します。
UTEST ( foo , bar ) {
char * a = "foo" ;
char * b = "bar" ;
ASSERT_STRNE ( a , b ); // pass!
ASSERT_STRNE ( a , a ); // fail!
}文字列xとyは、文字列xの長さに等しいと主張します。
UTEST ( foo , bar ) {
char * a = "foobar" ;
char * b = "foo" ;
ASSERT_STRNEQ ( a , a ); // pass!
ASSERT_STRNEQ ( b , b ); // pass!
ASSERT_STRNEQ ( a , b ); // pass!
}文字列xとyは、文字列xの長さに等しくないと主張します。
UTEST ( foo , bar ) {
char * a = "foobar" ;
char * b = "bar" ;
ASSERT_STRNNE ( a , b ); // pass!
ASSERT_STRNNE ( a , a ); // fail!
}浮動小数点値xとyは互いにepsilon距離内にあると断言します。
UTEST ( foo , bar ) {
float a = 42.0f ;
float b = 42.01f ;
ASSERT_NEAR ( a , b , 0.01f ); // pass!
ASSERT_NEAR ( a , b , 0.001f ); // fail!
}コードXが実行されると、Exception_Typeがスローされると主張します。
void foo ( int bar) {
if (bar == 1 )
throw std::range_error;
}
UTEST (foo, bar) {
ASSERT_EXCEPTION ( foo ( 1 ), std::range_error); // pass!
ASSERT_EXCEPTION ( foo ( 2 ), std::range_error); // fail!
ASSERT_EXCEPTION ( foo ( 1 ), std:: exception ); // fail!
}xが真(すなわちゼロ以外)を評価することを期待しています。
UTEST ( foo , bar ) {
int i = 1 ;
EXPECT_TRUE ( i ); // pass!
EXPECT_TRUE ( 42 ); // pass!
EXPECT_TRUE ( 0 ); // fail!
}xがfalse(すなわちゼロ)に評価されることを期待しています。
UTEST ( foo , bar ) {
int i = 0 ;
EXPECT_FALSE ( i ); // pass!
EXPECT_FALSE ( 1 ); // fail!
}xとyが等しいことを期待しています。
UTEST ( foo , bar ) {
int a = 42 ;
int b = 42 ;
EXPECT_EQ ( a , b ); // pass!
EXPECT_EQ ( a , 42 ); // pass!
EXPECT_EQ ( 42 , b ); // pass!
EXPECT_EQ ( 42 , 42 ); // pass!
EXPECT_EQ ( a , b + 1 ); // fail!
}xとyが等しくないことを期待しています。
UTEST ( foo , bar ) {
int a = 42 ;
int b = 13 ;
EXPECT_NE ( a , b ); // pass!
EXPECT_NE ( a , 27 ); // pass!
EXPECT_NE ( 69 , b ); // pass!
EXPECT_NE ( 42 , 13 ); // pass!
EXPECT_NE ( a , 42 ); // fail!
}xがy未満であることを期待しています。
UTEST ( foo , bar ) {
int a = 13 ;
int b = 42 ;
EXPECT_LT ( a , b ); // pass!
EXPECT_LT ( a , 27 ); // pass!
EXPECT_LT ( 27 , b ); // pass!
EXPECT_LT ( 13 , 42 ); // pass!
EXPECT_LT ( b , a ); // fail!
}xはy以下であると予想しています。
UTEST ( foo , bar ) {
int a = 13 ;
int b = 42 ;
EXPECT_LE ( a , b ); // pass!
EXPECT_LE ( a , 27 ); // pass!
EXPECT_LE ( a , 13 ); // pass!
EXPECT_LE ( 27 , b ); // pass!
EXPECT_LE ( 42 , b ); // pass!
EXPECT_LE ( 13 , 13 ); // pass!
EXPECT_LE ( 13 , 42 ); // pass!
EXPECT_LE ( b , a ); // fail!
}xがyよりも大きいことを期待しています。
UTEST ( foo , bar ) {
int a = 42 ;
int b = 13 ;
EXPECT_GT ( a , b ); // pass!
EXPECT_GT ( a , 27 ); // pass!
EXPECT_GT ( 27 , b ); // pass!
EXPECT_GT ( 42 , 13 ); // pass!
EXPECT_GT ( b , a ); // fail!
}xがy以上であることを期待しています。
UTEST ( foo , bar ) {
int a = 42 ;
int b = 13 ;
EXPECT_GE ( a , b ); // pass!
EXPECT_GE ( a , 27 ); // pass!
EXPECT_GE ( a , 13 ); // pass!
EXPECT_GE ( 27 , b ); // pass!
EXPECT_GE ( 42 , b ); // pass!
EXPECT_GE ( 13 , 13 ); // pass!
EXPECT_GE ( 42 , 13 ); // pass!
EXPECT_GE ( b , a ); // fail!
}文字列xとyが等しいと予想されます。
UTEST ( foo , bar ) {
char * a = "foo" ;
char * b = "bar" ;
EXPECT_STREQ ( a , a ); // pass!
EXPECT_STREQ ( b , b ); // pass!
EXPECT_STREQ ( a , b ); // fail!
}文字列XとYが等しくないことを期待しています。
UTEST ( foo , bar ) {
char * a = "foo" ;
char * b = "bar" ;
EXPECT_STRNE ( a , b ); // pass!
EXPECT_STRNE ( a , a ); // fail!
}文字列xとyは、文字列xの長さに等しいと予想しています。
UTEST ( foo , bar ) {
char * a = "foobar" ;
char * b = "foo" ;
EXPECT_STRNEQ ( a , a ); // pass!
EXPECT_STRNEQ ( b , b ); // pass!
EXPECT_STRNEQ ( a , b ); // pass!
}文字列xとyが文字列xの長さに等しくないことを期待しています。
UTEST ( foo , bar ) {
char * a = "foobar" ;
char * b = "bar" ;
EXPECT_STRNNE ( a , b ); // pass!
EXPECT_STRNNE ( a , a ); // fail!
}浮動小数点値xとyが互いにepsilon距離内にあることを期待しています。
UTEST ( foo , bar ) {
float a = 42.0f ;
float b = 42.01f ;
EXPECT_NEAR ( a , b , 0.01f ); // pass!
EXPECT_NEAR ( a , b , 0.001f ); // fail!
}コードXが実行されると、Exception_Typeがスローされることを期待しています。
void foo ( int bar) {
if (bar == 1 )
throw std::range_error;
}
UTEST (foo, bar) {
EXPECT_EXCEPTION ( foo ( 1 ), std::range_error); // pass!
EXPECT_EXCEPTION ( foo ( 2 ), std::range_error); // fail!
EXPECT_EXCEPTION ( foo ( 1 ), std:: exception ); // fail!
}コードXが実行されると、例外_typeがメッセージ例外_messageでスローされることを期待しています。
void foo ( int bar) {
if (bar == 1 )
throw std::range_error ( " bad bar " );
}
UTEST (foo, bar) {
EXPECT_EXCEPTION_WITH_MESSAGE ( foo ( 1 ), std::range_error, " bad bar " ); // pass!
EXPECT_EXCEPTION_WITH_MESSAGE ( foo ( 2 ), std::range_error, " bad bar2 " ); // fail!
EXPECT_EXCEPTION_WITH_MESSAGE ( foo ( 1 ), std:: exception , " bad bar " ); // fail!
}このマクロを使用すると、テストケースをスキップされているとマークできます。テストケースが実行されないこと。マクロを実行するとテストが実行されなくなり、 msgスキップの理由として報告し、テストを「スキップ」としてマークします。これらは障害前の実行の終了時に報告され、スキップされたテストケースでは、ゼロ以外のコードでプロセスが終了することはありません。
UTEST ( foo , bar ) {
UTEST_SKIP ( "Need to implement this test!" );
}さらに、障害テストにカスタムメッセージを入力する可能性を示すために、すべてのマクロを「_MSG」と呼ばれるサフィックスで使用できます。これは、障害の場合に印刷するカスタムメッセージのある文字列である追加のパラメーターを受信します。
例えば:
UTEST ( foo , bar ) {
int i = 1 ;
EXPECT_TRUE_MSG ( i , "custom message" ); // pass!
EXPECT_TRUE_MSG ( 42 , "custom message" ); // pass!
EXPECT_TRUE_MSG ( 0 , "custom message" ); // fail! (with the following output)
} test.cpp:42: Failure
Expected : true
Actual : false
Message : custom message
[ FAILED ] foo.bar (8086ns)
ライブラリは、ビルトイン整数、フローティングポイント、またはポインタータイプを主張することをサポートしています。
これは、パブリックドメインにリリースされた無料で邪魔されていないソフトウェアです。
誰でも、このソフトウェアがソースコード形式またはコンパイルされたバイナリとして、あらゆる目的、商業的または非営利的なものとして、およびあらゆる手段で、このソフトウェアを自由にコピー、変更、公開、使用、コンパイル、販売、または配布することができます。
著作権法を認識する管轄区域では、このソフトウェアの著者または著者は、ソフトウェアに対するすべての著作権の関心をパブリックドメインに捧げます。私たちは、この献身を大衆の利益のために、そして私たちの相続人と後継者を損なうために献身します。私たちは、この献身は、著作権法に基づくこのソフトウェアに対するすべての現在および将来の権利の永続性における放棄の明白な行為であることを意図しています。
このソフトウェアは、商品性、特定の目的への適合性、および非侵害の保証を含むがこれらに限定されない、明示的または黙示的なものを保証することなく、「現状のまま」提供されます。いかなる場合でも、著者は、契約、不法行為、またはその他の訴訟、ソフトウェア、またはソフトウェアの使用またはその他の取引に関連する、またはその他の契約の措置、またはその他の請求、損害、またはその他の責任について責任を負いません。
詳細については、http://unlicense.org/を参照してください。