一個簡單的一個標題解決方案,用於C/C ++的單元測試。
只需在您的代碼中#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,請使用TRUNK版本,它將按預期工作。
utest.h支持一些命令行選項:
--help輸出幫助消息--filter=<filter>將過濾測試用例(可用於重新運行一個特定的有害測試用例)。--list-tests將列出每行測試名稱。輸出名稱可以傳遞給--filter 。--output=<output>將輸出帶有測試結果的Xunit XML文件(Jenkins,Travis-CI和Appveyor可以分析測試結果)。--enable-mixed-units將使每個測試輸出能夠包含混合單元(S/MS/US/NS)。--random-order[=<seed>]將隨機化測試所在的順序。如果未提供可選參數,則使用隨機的啟動種子。 UTEST是一個單個標頭庫,可在C和C ++中啟用所有單元測試的樂趣。該庫旨在提供類似於Google的Googletest Framework類似的輸出:
[==========] Running 1 test cases.
[ RUN ] foo.bar
[ OK ] foo.bar (631ns)
[==========] 1 test cases ran.
[ PASSED ] 1 tests.
在一個C或C ++文件中,您必須調用Macro utest_main:
UTEST_MAIN ()這將調用utest.h,實例化所有測試櫃並運行單元測試框架。
另外,如果您想編寫自己的主體並致電utest.h,則可以在一個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宏帶有兩個參數 - 第一個是測試用例所屬的集合,第二個是測試的名稱。為了方便起見,這允許進行測試。
固定測試櫃是一個可以在多個測試櫃上共享的結構的結構。
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宏 - 即使它們在體內甚麼都不做。有時,您想反複使用相同的固定裝置和測試櫃,但可能會巧妙地更改一個變量。這是索引測試櫃進來的地方。
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的內容,我們提供了每個錯誤檢查條件的兩個變體 - 斷言和期望。如果斷言失敗,則測試案例將停止執行,並且UTEST.H將繼續下一個要運行的測試案例。如果期望失敗,將仍將執行測試案例的其餘部分,從而進行進一步的檢查。
我們目前提供以下宏位於UTEST中:
斷言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彼此之間的距離範圍內。
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時將拋出異常_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評估為true(即非零)。
UTEST ( foo , bar ) {
int i = 1 ;
EXPECT_TRUE ( i ); // pass!
EXPECT_TRUE ( 42 ); // pass!
EXPECT_TRUE ( 0 ); // fail!
}期望X評估為false(IE零)。
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時會拋出異常。
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時,except_type將會帶有消息except_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/