حل بسيط واحد لاختبار الوحدة لـ C/C ++.
فقط #include "utest.h" في الكود الخاص بك!
الأنظمة الأساسية المدعومة الحالية هي Linux و MacOS و Windows.
المترجمون المدعومون الحاليون هي GCC و Clang و MSVC's Cl.exe و Clang-Cl.exe.
كما أنه يعمل مع TCC ولكن مع تحذير: يفتقر أحدث إصدار من برنامج التحويل البرمجي TCC (الإصدار 0.9.27) إلى ميزة للعمل. تأكد من استخدام TCC مصححة بامتداد سمة المنشئ. شحن Ubuntu و Debian Linux Distros الأخير مع هذا التصحيح المدرجة بالفعل. إذا قمت بتجميع TCC بنفسك ، فاستخدم إصدار Trunk وسيعمل كما هو متوقع.
utest.h يدعم بعض خيارات سطر الأوامر:
--help لإخراج رسالة المساعدة--filter=<filter> سيقوم بتصفية حالات الاختبار التي يتم تشغيلها (مفيدة لإعادة تشغيل حالة اختبار مخالفة معينة).--list-tests قائمة TestNames ، واحدة لكل سطر. يمكن تمرير أسماء الإخراج إلى --filter .--output=<output> سوف يخرج ملف XML Xunit مع نتائج الاختبار (يمكن لـ Jenkins و Travis-Ci و Appveyor تحليل نتائج الاختبار).--enable-mixed-units الإخراج لكل اختبار احتواء وحدات مختلطة (S/MS/US/NS).--random-order[=<seed>] سوف يعرض عشوائيًا على الترتيب الذي يتم فيه إجراء الاختبارات. إذا لم يتم توفير الوسيطة الاختيارية ، فسيتم استخدام بذرة بداية عشوائية. UTEST هي مكتبة رأس واحدة لتمكين كل متعة اختبار الوحدة في C و C ++. تم تصميم المكتبة لتوفير إخراج مماثل لإطار Google الأكثر:
[==========] Running 1 test cases.
[ RUN ] foo.bar
[ OK ] foo.bar (631ns)
[==========] 1 test cases ran.
[ PASSED ] 1 tests.
في ملف C أو C ++ واحد ، يجب عليك الاتصال بالماكرو utest_main:
UTEST_MAIN ()سيؤدي ذلك إلى استدعاء uTest.h ، إنشاء جميع حالات testcases وتشغيل إطار اختبار الوحدة.
بدلاً من ذلك ، إذا كنت ترغب في كتابة الرئيسية الخاصة بك والاتصال بـ 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 );
}يأخذ Macro UTEST معلمتين - أول هو المجموعة التي تنتمي إليها حالة الاختبار ، والثانية هي اسم الاختبار. هذا يسمح بتجميع الاختبارات للراحة.
اختبار testcase المركب هو أحد البنية التي يتم إنشاء مثيل لها يمكن مشاركتها عبر عوامل اختبار متعددة.
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 - حتى لو لم يفعلوا شيئًا في الجسم.في بعض الأحيان ، تريد استخدام نفس المباراة والحرف المتكررة بشكل متكرر ، ولكن ربما يغير بمهارة متغير واحد في الداخل. هذا هو المكان الذي تأتي فيه حالات testcases المفهرسة.
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 مع قضية الاختبار التالية المراد تشغيلها. إذا فشل توقع ، فلا يزال سيتم تنفيذ ما تبقى من حالة الاختبار ، مما يسمح بإجراء مزيد من عمليات الفحص.
نحن نقدم حاليًا وحدات الماكرو التالية لاستخدامها في أوتيست:
يؤكد أن X يقييم إلى True (على سبيل المثال. غير صفري).
UTEST ( foo , bar ) {
int i = 1 ;
ASSERT_TRUE ( i ); // pass!
ASSERT_TRUE ( 42 ); // pass!
ASSERT_TRUE ( 0 ); // fail!
}يؤكد أن X يقييم إلى خطأ (على سبيل المثال صفر).
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!
}يؤكد أنه سيتم طرح استثناء _type عند تنفيذ الرمز X.
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 يقييم إلى خطأ (أي صفر).
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!
}يتوقع أن يتم طرح استثناء _type عند تنفيذ الرمز 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!
}يتوقع أن يتم طرح استثناء _type مع Message Exception_message عند تنفيذ الرمز X.
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/