تشغيل اختبارات الوحدة محليا في STM32CubeIDE تحت ويندوز

مقدمة


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


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


هناك ثلاث طرق لتشغيل اختبارات الوحدات للأنظمة الأساسية المدمجة:


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

يوفر هذا المنشور طريقة لتكوين اختبارات الوحدة في بيئة STM32CubeIDE ، استنادًا إلى Eclipse والمخصصة للتطوير لوحدات التحكم في عائلة STM32. لغة التطوير هي لغة C ، ولكن الاختبارات مكتوبة بلغة C ++. سيتم تشغيل الاختبارات على جهاز مضيف Windows باستخدام Cygwin. كإطار اختبار ، يتم استخدام Google Test. سيتم عرض النتائج في نافذة مكون إضافي خاصة لاختبار الوحدات ، ويمكن إطلاقها بضغطة واحدة من المشروع لـ STM32:



تعد الطريقة الموصوفة مناسبة لبيئات التطوير الأخرى المستندة إلى Eclipse ، ما لم تكن الشركات المصنعة الجيدة قد خفضتها كثيرًا من أجل راحة المطورين. ستعمل هذه الطريقة أيضًا مع CubeIDE في نظام Linux ، دون الحاجة إلى الإزعاج من Cygwin.


سوف تحتاج


  1. Cygwin 3.0.7 x86 (نظرًا لأن الاختبارات عبارة عن متحكم 32 بت ، سنستخدم بيئة 32 بت على نظام أساسي 64 بت أيضًا)
  2. STM32CubeIDE 1.0.2 لنظام التشغيل Windows.
  3. جوجل اختبار الإطار 1.8.1

تثبيت Cygwin و STM32CubeIDE


سيغوين


تثبيت Cygwin ، الإصدار x86. في المثبت ، حدد حزم إضافية: gcc-core ، g ++ ، binutils ، automake ، autoconf ، cmake ، libtool ، gdb ، make. يمكنك تثبيت أحدث إصدارات مستقرة من الحزم.



تحتاج أيضًا إلى تسجيل متغيرات البيئة:


PATH: ...؛ C: \ <path_to_Cygwin> \ Cygwin \ bin؛ C: \ <path_to_Cygwin> \ Cygwin \ lib
classpath: C: \ <path_to_Cygwin> \ Cygwin \ lib


STM32CubeIDE


تم تثبيت البيئة كالمعتاد. يُنصح بتثبيت CubeIDE بعد Cygwin ، لأنه في هذه الحالة سوف يلتقط Cube سلسلة أدوات Cygwin الحالية.


أولاً ، قم بإنشاء مشروع C ++ لمنصة x86 Cygwin. سنحتاج إليها ، أولاً ، للتحقق من وظائف سلسلة الأدوات ، وثانياً ، سوف نستخدمها "كمتبرع" في تكوين التجميع للمشروع الرئيسي.


اختر ملف> جديد> مشروع C / C ++. حدد C ++ Managed Build. نخلق مشروع نوع hello world لسلسلة أدوات Cygwin GCC:



بعد ذلك ، ستحتاج إلى اختيار تكوينات التجميع المراد إنشاؤها. مجرد تصحيح يكفي.
يمكنك الآن التحقق من أن المشروع يسير باختيار Project> Build All. من المستحسن أيضًا التحقق من تصحيح الأخطاء ضمن Cygwin عن طريق تشغيل Run> Debug As> Local C / C ++ Application. سيقوم التطبيق بإخراج "Hello world" إلى وحدة التحكم داخل CubeIDE.


لكي يعرض المصحح خطوطًا قابلة للتنفيذ في ملفات التعليمات البرمجية المصدر ، تحتاج إلى تكوين عرض المسار. في نافذة> تفضيلات النافذة ، في علامة التبويب C / C ++> تصحيح ، حدد مسار البحث عن المصدر وإضافة عرض جديد: إضافة> تعيين المسار. في النافذة ، تحتاج إلى تسمية شيء مثل عرض جديد وإضافة خطوط للأقراص الموجودة في النظام:


  • \ cygdrive \ c - C: \
  • \ cygdrive \ g - G: \



لإجراء اختبار جميل ، سنحتاج أيضًا إلى مكون إضافي لـ Eclipse مع دعم لاختبارات الوحدات لـ C ++. يتم تثبيته مباشرة من STM32CubeIDE: القائمة تعليمات> تثبيت برنامج جديد ، ثم حدد Eclipse Repository وتثبيت البرنامج المساعد C / C ++ Unit Testing Support.



بناء مكتبة اختبار جوجل


يمكن العثور على الكود المصدري للمكتبة على: https://github.com/google/googletest/tree/release-1.8.1
قم بفك المصادر ، انتقل إلى دليل googletest-release-1.8.1 باستخدام محطة Cygwin ، وقم بتشغيل:


cmake . make 

بعد التجميع الناجح ، سيكون ملف المكتبة الثابتة في ./googlemock/lib/libgtest.a ، وستكون ملفات الرأس في دليل ./googletest/include/gtest/. ستحتاج إلى نسخ إلى مشروعنا (أو كتابة المسار إلى هذه الملفات في إعدادات المشروع).


إنشاء مشروع لـ STM32


تصميم لوحة التصحيح STM32L476G-DISCO. لن يكون المثال معقدًا للغاية - فهناك مؤشران LED على اللوحة ، دعهما يُظهران عدادًا ثنائيًا من 00 إلى 11. سنقوم بتنفيذ وحدة منفصلة للعداد ، موصوفة في زوج من ملفات .h و .c ، وكتابة اختبار لذلك.
يمكن إنشاء المشروع كالمعتاد ، باستخدام أداة تكوين المكعب ، الشيء الرئيسي هو التأكد من تكوين دبابيس PB2 و PE8 كمخرجات رقمية. عند إنشاء مشروع ، سيكون من الأفضل تحديد النوع - C ++ ، وستكون هناك حاجة لتجميع الاختبارات (لا يزال سيتم ترجمة التعليمات البرمجية الرئيسية بواسطة برنامج التحويل البرمجي C). سيكون تحويل مشروع من C ممكنًا لاحقًا ، وذلك بالنقر فوق اسم مشروع RMB واختيار "تحويل إلى C ++".


للتجميع تحت MK والاختبارات نحتاج إلى تكوينين مختلفين للتجميع. في هذه التكوينات ، سيتم جمع مجموعات مختلفة من الملفات - ستحصل المجموعات الرئيسية على الوحدات النمطية للعمل مع الأجهزة والوحدات التي تم اختبارها ، وسيحصل الاختبار على نفس الوحدات النمطية التي تم اختبارها وملفات الاختبار. لذلك ، سنقوم بإنشاء أدلة مختلفة في جذر المشروع - التطبيق برمز التطبيق لـ MK (يمكنك ببساطة إعادة تسمية دليل Src الذي أنشأه Cube) ، والمشتركة للوحدات النمطية التي لا تعتمد على الحديد (والتي سنختبرها) ، والاختبارات للاختبارات. يمكن استبعاد الدلائل من التجميع بالنقر فوق RMB باسمهم ، قائمة Resource Configuration> Exclude from build.


أضف وحدة العداد الخاصة بنا إلى الدليل العام:


رمز Led_counter

(Led_counter.h):


 #ifndef LED_COUNTER_H_ #define LED_COUNTER_H_ #include <stdint.h> void Led_Counter_Init(); uint8_t Led_Counter_Get_Next(); #endif /* LED_COUNTER_H_ */ 

led_counter.cpp:


 #include "led_counter.h" static uint8_t led_cnt_state = 0; void Led_Counter_Init() { led_cnt_state = 0; } uint8_t Led_Counter_Get_Next() { if(++led_cnt_state > 3) led_cnt_state = 0; return led_cnt_state; } 

يجب إضافة الدلائل الشائعة واختبارات إلى مسار البحث عن ملفات التضمين: خصائص المشروع (الخصائص)> C / C ++ عام> المسارات والرموز> يشمل.


أضف إلى العمل مع المصابيح الرئيسية


شظية main.c

main.c:


 /* USER CODE BEGIN Includes */ #include "led_counter.h" /* USER CODE END Includes */ … int main(void) { … /* USER CODE BEGIN WHILE */ Led_Counter_Init(); uint8_t led_state = 0; while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ led_state = Led_Counter_Get_Next(); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, led_state & (1<<0)); HAL_GPIO_WritePin(GPIOE, GPIO_PIN_8, led_state & (1<<1)); HAL_Delay(500); } /* USER CODE END 3 */ … } 

يجب أن يتم تجميع المشروع وتشغيله ، ويجب أن تومض المصابيح.


اختبارات الكتابة


الآن بعد أن بدأ كل شيء.


قم بإنشاء تكوين بناء جديد من خلال خصائص المشروع - خصائص> C / C ++ Build> الإعدادات> إدارة التكوينات. لن تسمح لك CubeIDE بإنشاء تكوين للبناء ضمن Cygwin ، لذلك انسخه من المشروع الذي أنشأناه مسبقًا:



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


  • يشمل - الاختبارات / المؤتمر الوطني العراقي ، المشترك / المؤتمر الوطني العراقي
  • المكتبات - gtest
  • مسارات المكتبة - الاختبارات / Lib
  • موقع المصدر - / <prj_name> / العام و / <prj_name> / الاختبارات (استبدل <prj_name> باسم المشروع)

بعد ذلك ، انسخ مكتبة gtest - ملف .a إلى دليل الاختبارات / Lib إلى المشروع ، وملفات الرأس في مجلد gtest - إلى مجلد Tests / Inc. في مجلد الاختبارات ، قم بإنشاء ملف main.cpp جديد سيتم تشغيل الاختبارات فيه. محتوياته قياسية:


MAIN.CPP:


 /* * Unit tests main file */ #include "gtest/gtest.h" int main(int argc, char *argv[]) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } 

أيضًا ، للتحقق من الإعداد ، سننشئ اختبارًا واحدًا للتحقق من أن حجم المؤشر هو 32 بت في بيئتنا (نريد أن نتأكد من أنه هو نفسه الموجود في المتحكم الدقيق ، ولهذا قمنا بتعيين Cygwin 32 بت).


قم بإنشاء ملف اختبار test_platform.cpp التالي:


 #include "gtest/gtest.h" TEST(PlatformTest, TestPointerSize) { //Check pointer size is 32 bit ASSERT_EQ(sizeof(void*)*8, 32U); } 

الآن ، إذا تم تشغيل المشروع كالتطبيق C ++ المعتاد ، فسيحتوي إخراج التصحيح على رسالة من اختبار Google تفيد بأن جميع الاختبارات قد مرت.


يجب أن يبدو هيكل المشروع كما يلي:


الآن سوف نكتب اختبارات لوحدة عداد LED الخاصة بنا. يمكن العثور على ملفات الاختبار في مجلد الاختبارات:


test_led_counter.cpp
 #include "gtest/gtest.h" extern "C" { #include "led_counter.h" } // Test fixture class LedCounterTest: public ::testing::Test { protected: void SetUp() { Led_Counter_Init(); } }; // Check initial value TEST_F(LedCounterTest, TestInitialValue) { Led_Counter_Init(); ASSERT_EQ(Led_Counter_Get_Next(), 1); } // Check how value is incremented TEST_F(LedCounterTest, TestIncrementValue) { Led_Counter_Init(); unsigned int val = Led_Counter_Get_Next(); for(int i=0;i<1;i++) { ASSERT_EQ(Led_Counter_Get_Next(), ++val); } } // Check how value return to 0 after 3 TEST_F(LedCounterTest, TestZeroCrossing) { Led_Counter_Init(); for(int i=0;i<3;i++) { Led_Counter_Get_Next(); } ASSERT_EQ(Led_Counter_Get_Next(), 0); } 

لكي يتم عرض نتائج الاختبار في نافذة جميلة ، تحتاج إلى إنشاء تكوين تشغيل جديد في قائمة Run> Debug Configurations. يسمح لك المكوّن الإضافي المثبت بإنشاء تكوينات من النوع C / C ++ Unit. قم بإنشائه ، واستدعي Run Tests ، وحدد تكوين التجميع "اختبار" المستخدم وألغ تحديد مربع الاختيار "stop عند بدء التشغيل" في علامة التبويب Debugger. بعد ذلك ، يمكن بدء التكوين.


لإظهار نافذة تظهر فيها النتائج ، حددها في نافذة> عرض عرض> آخر> C / C ++> وحدة C / C ++.



القيام به! الآن يمكن تجميع المشروع وتشغيله تحت الهدف MK كالمعتاد. عندما تحتاج إلى تشغيل الاختبارات المحلية ، عند تشغيل تكوين Run Tests ، سيتم إعادة إنشاء المشروع تلقائيًا لـ x86 ، ستقوم البيئة بإجراء الاختبارات وإظهار النتيجة.


أدب


  1. جيه غرينينغ. التطوير القائم على الاختبار لـ Embedded C. - العمل الأساسي في اختبار الوحدة للأنظمة المدمجة وتطبيق منهجية TDD.
  2. https://uncannier.com/unit-testing-of-embedded-firmware-part-1-software-confucius/ - اختبار وحدة x86 لرمز متحكم في استوديو Texas Instruments Code Composer ، CppUTest framework
  3. http://blog.atollic.com/why-running-your-embedded-arm-cortex-code-on-a-host-pc-is-a-good-thing - مقالة عن السبب في أنه قد يكون من المفيد تشغيل التعليمات البرمجية عن متحكم على منصة سطح المكتب

Source: https://habr.com/ru/post/ar469367/


All Articles