شرح - اختبار وحدة اختبار C




unit testing شرح (20)

لقد عملت على نظام مضمن هذا الصيف مكتوبًا على التوالي C. كان مشروعًا حاليًا قد تولته الشركة التي أعمل من أجلها. لقد أصبحت معتادين على كتابة اختبارات الوحدة في جافا باستخدام JUnit ، لكننا كنا في خضم أفضل طريقة لكتابة اختبارات الوحدة للرمز الحالي (الذي يحتاج إلى إعادة بيع ديون) بالإضافة إلى رمز جديد يضاف إلى النظام.

هل هناك أي طريقة لجعل وحدة اختبار C رمز عادي سهلة مثل وحدة اختبار رمز جافا مع ، على سبيل المثال ، JUnit ؟ وستكون أي فكرة يمكن أن تنطبق على وجه التحديد على التنمية المدمجة (التجميع المتقاطع لمنصة الذراع-لينكس) موضع تقدير كبير.



أسلوب واحد لاستخدامه هو تطوير كود اختبار الوحدة مع إطار عمل C ++ xUnit (و C ++ compiler) ، مع الحفاظ على المصدر للنظام المستهدف كوحدات C.

تأكد من أن تقوم بانتظام بتجميع مصدر C الخاص بك ضمن برنامج التحويل البرمجي الخاص بك ، بشكل تلقائي مع اختبارات الوحدة الخاصة بك إن أمكن.


أنا حاليا باستخدام إطار اختبار وحدة CuTest:

http://cutest.sourceforge.net/

إنها مثالية للأنظمة المدمجة لأنها خفيفة الوزن وبسيطة للغاية. لم يكن لدي أي مشاكل في الحصول على العمل على منصة الهدف وكذلك على سطح المكتب. بالإضافة إلى كتابة اختبارات الوحدة ، كل ما هو مطلوب هو:

  • تضمين ملف رأس أينما كنت استدعاء إجراءات CuTest
  • ملف "C" إضافي واحد يتم تجميعه / ربطه في الصورة
  • بعض التعليمات البرمجية البسيطة المضافة إلى الرئيسي لإعداد واستدعاء اختبارات الوحدة - لدي هذا فقط في وظيفة main () خاصة يتم تجميعها إذا تم تعريف UNITTEST أثناء الإنشاء.

يحتاج النظام إلى دعم كومة الذاكرة المؤقتة وبعض وظائف stdio (التي لا تحتوي جميع الأنظمة المضمنة). لكن الرمز بسيط بما فيه الكفاية بحيث يمكنك العمل على الأرجح في بدائل لتلك المتطلبات إذا كان النظام الأساسي الخاص بك لا يحتوي عليها.

باستخدام بعض الاستخدامات الحكيمة لـ extern "C" {} ، فإنه يدعم أيضًا اختبار C ++ على ما يرام.


أنا شخصياً أحب إطار عمل اختبار Google .

الصعوبة الحقيقية في اختبار كود C هي كسر الاعتماديات على الوحدات الخارجية بحيث يمكنك عزل الكود في الوحدات. قد يكون هذا مشكلة خاصة عندما تحاول إجراء اختبارات حول الشفرة القديمة. في هذه الحالة غالباً ما أجد نفسي باستخدام رابط لاستخدام وظائف الروتين في الاختبارات.

هذا ما يشير إليه الناس عندما يتحدثون عن " طبقات ". في C ، يكون خيارك الوحيد هو استخدام المعالج المسبق أو الرابط للتخلص من الاعتماديات الخاصة بك.

قد يظهر أحد أجنحة الاختبار النموذجية في أحد مشاريع C على النحو التالي:

#include "myimplementationfile.c"
#include <gtest/gtest.h>

// Mock out external dependency on mylogger.o
void Logger_log(...){}

TEST(FactorialTest, Zero) {
    EXPECT_EQ(1, Factorial(0));
}

لاحظ أنك بالفعل تتضمن الملف C وليس ملف الرأس . هذا يعطي ميزة الوصول إلى جميع أعضاء البيانات الثابتة. هنا أستهزأ بالمسجل الخاص بي (والذي قد يكون في logger.o ويعطي تطبيقًا فارغًا ، وهذا يعني أن ملف الاختبار يجمع ويرتبط بشكل مستقل عن بقية قاعدة الكود وينفذ في عزلة.

أما بالنسبة لجمع التعليمات البرمجية المتقاطعة ، لهذا العمل تحتاج إلى مرافق جيدة على الهدف. لقد فعلت ذلك مع الصليب googletest جمعت لينكس على بنية PowerPC. هذا منطقي لأنه هناك لديك قذيفة كاملة ونظام التشغيل لجمع نتائجك. بالنسبة للبيئات الأقل ثراء (التي أقوم بتصنيفها كأي شيء بدون نظام تشغيل كامل) ، يجب أن تقوم ببناء وتشغيل المضيف. يجب عليك القيام بذلك على أي حال حتى تتمكن من تشغيل الاختبارات تلقائيا كجزء من البناء.

أجد اختبار C ++ رمز عموما أسهل بكثير يرجع ذلك إلى حقيقة أن رمز OO بشكل عام أقل بكثير من إجرائية (بالطبع هذا يعتمد كثيرا على نمط الترميز). أيضا في C ++ يمكنك استخدام الحيل مثل حقن التبعية وطريقة تجاوز للحصول على طبقات في التعليمات البرمجية التي يتم تغليفها خلاف ذلك.

يمتلك Michael Feathers كتابًا ممتازًا حول اختبار الرمز القديم . في أحد الفصول يغطي تقنيات للتعامل مع رمز غير OO الذي أوصي به بشدة.

تحرير : لقد كتبت مشاركة مدونة عن وحدة اختبار رمز إجرائي ، مع مصدر متاح على جيثب .

تحرير : هناك كتاب جديد يخرج من المبرمجين البراغماتيين الذي يعالج على وجه التحديد اختبار كود الوحدة C الذي أوصي به بشدة .


أنا مندهش من أن أحدا لم يذكر كتر (http://cutter.sourceforge.net/) يمكنك اختبار C و C ++ ، فإنه يدمج بسلاسة مع autotools ولديه برنامج تعليمي رائع حقا.


أولاً ، انظر هنا: http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C

لدى شركتي مكتبة C يستخدمها عملاؤنا. نستخدم CxxTest (مكتبة اختبار وحدة C ++) لاختبار التعليمات البرمجية. CppUnit سوف تعمل أيضا. إذا كنت عالقا في C ، أود أن أوصي RCUNIT (ولكن CUnit جيد جدا).


إذا كنت معتادا على JUnit ثم أوصي CppUnit. http://cppunit.sourceforge.net/cppunit-wiki

هذا هو افتراض أن لديك مترجم c ++ لإجراء اختبارات الوحدة. إذا لم يكن الأمر كذلك يجب أن أتفق مع آدم روزنفيلد أن التحقق هو ما تريد.


إطار اختبار وحدة واحدة في C هو Check ؛ يمكن العثور here على قائمة بأطر اختبار الوحدات في C ويتم استنساخها أدناه. استنادًا إلى عدد وظائف المكتبة القياسية التي لديك وقت التشغيل ، قد تتمكن أو لا تستطيع استخدام أحد هذه.

AceUnit

فواتير AceUnit (Advanced C و Embedded Unit) نفسها كإطار اختبار وحدة C رمز وحدة مريحة. يحاول محاكاة JUnit 4.x ويتضمن إمكانات مثل الانعكاس. يمكن استخدام AceUnit في بيئات قيد الموارد ، مثل تطوير البرامج المضمنة ، والأهم أنه يعمل بشكل جيد في البيئات حيث لا يمكنك تضمين ملف رأس قياسي قياسي واحد ولا يمكن استدعاء دالة C قياسية واحدة من مكتبات ANSI / ISO C. كما أن لديها منفذ ويندوز. لا يستخدم الشوك لإيقاع الإشارات ، على الرغم من أن المؤلفين قد أعربوا عن اهتمامهم بإضافة مثل هذه الميزة. انظر الصفحة الرئيسية AceUnit .

جنو Autounit

كثير على طول نفس الخطوط مثل Check ، بما في ذلك التوقع لتشغيل اختبارات الوحدة في مساحة عنوان منفصلة (في الواقع ، استعار المؤلف الأصلي لـ Check الفكرة من GNU Autounit). يستخدم GNU Autounit GLib على نطاق واسع ، مما يعني أن الربط يحتاج إلى خيارات خاصة ، ولكن هذا قد لا يمثل مشكلة كبيرة بالنسبة لك ، خاصة إذا كنت تستخدم بالفعل GTK أو GLib. انظر الصفحة الرئيسية لـ GNU Autounit .

كونيت

كما يستخدم GLIB ، ولكن لا شوكة لحماية مساحة العنوان من اختبارات الوحدة.

كونيت

قياسي C ، مع وجود خطط للتنفيذ Win32 واجهة المستخدم الرسومية. لا يقوم حاليا بتفريغ أو حماية مساحة العنوان من اختبارات الوحدة. في التطور المبكر. انظر الصفحة الرئيسية CUnit .

طيف

إطار عمل بسيط يحتوي على ملف واحد فقط. c وملف .h واحد يتم إسقاطه في شجرة المصدر الخاصة بك. انظر الصفحة الرئيسية CuTest .

CppUnit

إطار اختبار وحدة رئيس الوزراء ل C ++. يمكنك أيضا استخدامه لاختبار C رمز. إنه مستقر ، مطور بنشاط ، ولديه واجهة المستخدم الرسومية. الأسباب الرئيسية لعدم استخدام CppUnit لـ C هي أولاً أنها كبيرة جدًا ، وثانيًا عليك كتابة اختباراتك في C ++ ، مما يعني أنك تحتاج إلى مترجم C ++. إذا كانت هذه لا تبدو مثل المخاوف ، فمن الجدير بالتأكيد النظر ، جنبا إلى جنب مع غيرها من أطر اختبار وحدة C ++. انظر الصفحة الرئيسية CppUnit .

embUnit

embUnit (الوحدة المدمجة) هو إطار اختبار وحدة آخر للأنظمة المضمنة. هذا واحد يبدو أنه حل محله AceUnit. الصفحة الرئيسية للوحدة المدمجة .

MinUnit

مجموعة صغيرة من وحدات الماكرو وهذا كل شيء! الهدف هو إظهار مدى سهولة اختبار الوحدة البرمجية الخاصة بك. انظر الصفحة الرئيسية MinUnit .

CUnit للسيد اندو

تطبيق CUnit الذي هو جديد إلى حد ما ، وعلى ما يبدو لا يزال في مرحلة مبكرة من التطور. انظر CUnit للسيد أندو الصفحة الرئيسية .

تم آخر تحديث لهذه القائمة في مارس 2008.

الآخرين:

CMocka

CMocka هو إطار اختبار لـ C مع دعم الكائنات الوهمية. إنه سهل الاستخدام والإعداد. الصفحة الرئيسية الرسمية cmocka.org .

معيار

المعيار هو إطار اختبار وحدة C عبر النظام الأساسي يدعم تسجيل الاختبار التلقائي والاختبارات ذات المعلمات والنظريات والتي يمكن أن تخرج إلى تنسيقات متعددة ، بما في ذلك TAP و JUnit XML. يتم تشغيل كل اختبار في العملية الخاصة به ، بحيث يمكن الإبلاغ عن الإشارات أو الأعطال أو اختبارها إذا لزم الأمر. راجع الصفحة الرئيسية لمعايير للحصول على مزيد من المعلومات.

HWUT

HWUT هي أداة اختبار عامة مع دعم كبير لـ C. ويمكن أن تساعد في إنشاء Makefiles ، وتوليد حالات اختبار ضخمة مشفرة في "جداول التكرار" الحد الأدنى ، والمشي على طول أجهزة الدولة ، وتوليد C- بذرات وأكثر من ذلك. النهج العام فريد من نوعه: تستند الأحكام على "stdout stdout / bad stdout جيد". وظيفة المقارنة ، على الرغم من ذلك ، هي مرنة. وبالتالي ، يمكن استخدام أي نوع من البرنامج النصي للتحقق. يمكن تطبيقه على أي لغة يمكن أن تنتج مخرجات قياسية. انظر الصفحة الرئيسية HWUT .


بعد قراءة Minunit ، اعتقدت أن طريقة أفضل كانت أساس الاختبار في تأكيد الماكرو الذي استخدمه كثيرًا مثل تقنية البرامج الدفاعية. لذلك أنا استخدم نفس الفكرة من Minunit مختلطة مع تأكيد القياسية. يمكنك رؤية إطار العمل الخاص بي (اسم جيد يمكن أن يكون NoMinunit) في مدونة k0ga



في حالة استهداف الأنظمة الأساسية Win32 أو وضع kernel NT ، يجب أن يكون لديك نظرة على cfix .


قد ترغب أيضًا في إلقاء نظرة على libtap ، إطار اختبار C الذي يخرج بروتوكول اختبار Anything Protocol (TAP) ، وبالتالي فإنه يتكامل بشكل جيد مع مجموعة متنوعة من الأدوات التي تظهر لهذه التقنية. يتم استخدامه غالبًا في عالم اللغة الديناميكي ، ولكنه سهل الاستخدام وأصبح شائعًا جدًا.

مثال:

#include <tap.h>

int main () {
    plan(5);

    ok(3 == 3);
    is("fnord", "eek", "two different strings not that way?");
    ok(3 <= 8732, "%d <= %d", 3, 8732);
    like("fnord", "f(yes|no)r*[a-f]$");
    cmp_ok(3, ">=", 10);

    done_testing();
}

لقد استخدمت RCUNIT للقيام ببعض اختبارات الوحدة للشفرة المضمنة على جهاز الكمبيوتر قبل الاختبار على الهدف. تجريد واجهة الأجهزة الجيدة مهم آخر endianness وسجلات الذاكرة المعينة سوف تقتل لك.


لقد كتبنا CHEAT (مستضافًا على GitHub ) لسهولة الاستخدام وسهولة الحمل.

ليس لها اعتماديات ولا تحتاج إلى تثبيت أو تهيئة. مطلوب فقط ملف رأس وحالة اختبار.

#include <cheat.h>

CHEAT_TEST(mathematics_still_work,
    cheat_assert(2 + 2 == 4);
    cheat_assert_not(2 + 2 == 5);
)

تجتمع الاختبارات في برنامج قابل للتنفيذ يهتم بتشغيل الاختبارات والإبلاغ عن نتائجها.

$ gcc -I . tests.c
$ ./a.out
..
---
2 successful of 2 run
SUCCESS

لديها ألوان جميلة جدا.


هناك CUnit

والوحدة المدمجة هي إطار اختبار الوحدة لنظام C المضمنة. تم نسخ تصميمها من JUnit و CUnit وأكثر من ذلك ، ثم تم تكييفها إلى حد ما لنظام Embedded C. لا تتطلب وحدة مدمجة lds std. يتم تخصيص كافة الكائنات إلى منطقة const.

Tessy بأتمتة اختبار الوحدة للبرامج المضمنة.


هناك إطار اختبار وحدة أنيق لـ C مع دعم للأشياء الوهمية المسماة cmocka . إنها تتطلب فقط مكتبة C القياسية ، وتعمل على مجموعة من منصات الحوسبة (بما في ذلك البرامج المدمجة) ومع المجمعات المختلفة.

كما أن لديها دعمًا لتنسيقات إخراج الرسائل المختلفة مثل Subunit و Test Anything Protocol وتقارير jUnit XML.

تم إنشاء cmocka أيضًا للعمل على الأنظمة الأساسية المضمّنة ولديه أيضًا دعم Windows.

اختبار بسيط يشبه هذا:

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>

/* A test case that does nothing and succeeds. */
static void null_test_success(void **state) {
    (void) state; /* unused */
}

int main(void) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(null_test_success),
    };
    return cmocka_run_group_tests(tests, NULL, NULL);
}

API موثقة بالكامل والعديد من الأمثلة جزء من شفرة المصدر.

للبدء مع cmocka يجب عليك قراءة المقال على LWN.net: اختبار الوحدة مع كائنات وهمية في C

تم إصدار cmocka 1.0 في فبراير 2015.


يقدم كتاب Michael Feather "Working Effectively with Legacy Code" الكثير من التقنيات الخاصة باختبار الوحدة خلال تطوير C.

هناك تقنيات متعلقة بحقن التبعية الخاصة بـ C والتي لم أراها في أي مكان آخر.


يمكنني استخدام CxxTest c / c ++ مضمنة (بشكل أساسي C ++).

أنا أفضل CxxTest لأنه يحتوي على برنامج نصي بيرل / بيثون لبناء عداء الاختبار. بعد منحدر صغير للحصول على الإعداد (أصغر حتى عندما لا تضطر إلى كتابة عداء الاختبار) ، فإنه من السهل استخدام (يتضمن عينات ووثائق مفيدة). كان معظم العمل هو إعداد "الأجهزة" التي تصل إلى الكود بحيث أتمكن من اختبار الوحدة / الوحدة بشكل فعال. بعد ذلك من السهل إضافة حالات اختبار وحدة جديدة.

كما ذكرنا سابقًا ، إنه إطار اختبار وحدة C / C ++. لذلك سوف تحتاج إلى مترجم C ++.

CxxTest دليل المستخدم CxxTest Wiki


API Sanity Checker - إطار اختبار لمكتبات C / C ++:

مولد تلقائي لاختبارات الوحدة الأساسية لمكتبة C / C ++ مشتركة. وهي قادرة على توليد بيانات مدخلات معقولة (في معظم الحالات ، ولكن ليس كلها لحالات) للمعلمات وتؤلف حالات اختبار بسيطة ("التعقل" أو "الضحلة") لكل وظيفة في API من خلال تحليل الإعلانات في العنوان الملفات.

تسمح جودة الاختبارات المتولدة بالتحقق من عدم وجود أخطاء فادحة في حالات الاستخدام البسيط. الأداة قادرة على بناء وتنفيذ الاختبارات التي تم إنشاؤها وكشف الأعطال (segfaults) ، إحباط ، جميع أنواع الإشارات المنبعثة ، رمز إرجاع البرنامج غير الصفر وبرنامج معلق.

أمثلة:


CppUTest - إطار موصى به للغاية لاختبار وحدة C رمز.

يتم كتابة الأمثلة في الكتاب المذكور في هذا الموضوع TDD لـ C المضمنة باستخدام CppUTest.





embedded