بدء الاستخدام مع CppUTest

Bird

14‏/05‏/2017

البريد الإلكتروني

1 min read

بدء الاستخدام مع CppUTest

النقاط الرئيسية

    • CppUTest هو إطار عمل اختبار خفيف الوزن بأسلوب xUnit يتم صيانته بفعالية للغات C/C++، مع طبقة تكامل C تعمل بشكل متكامل حتى في قواعد الشيفرات الثقيلة باستخدام C.

    • يمكنك تثبيته عبر مديري الحزم (توزيعات Linux، Homebrew) أو استنساخ مستودع GitHub.

    • يتكون الإعداد الأدنى من:

      • دليل إنتاج src/،

      • دليل اختبار t/،

      • عارض الاختبار (CommandLineTestRunner)، و

      • وحدات الاختبار باستخدام TEST_GROUP وTEST() كتل.

    • يوفر CppUTest مساعد MakefileWorker.mk الذي يبسط بناء الاختبارات وربط المكتبات والتعامل مع الأعلام.

    • كشف تسرب الذاكرة مُفعل بشكل افتراضي من خلال تجاوزات malloc/free، لإكتشاف التسربات ضمن شيفرات المصدر المختبرة.

    • تغطية الشيفرة عبر gcov تتكامل بسهولة بتمكين CPPUTEST_USE_GCOV=Y، مما ينتج تقارير تغطية كاملة وملخصات HTML.

    • يتضمن الإطار ميزات متقدمة: المحاكاة، الإضافات، السكربتات المساعدة، والتوافق المباشر مع C - المفيد لقواعد الشيفرات المؤسسية المعقدة.

أبرز الأسئلة والأجوبة

  • ما هو CppUTest ولماذا نستخدمه؟

    إنه إطار عمل اختبار xUnit قوي لـ C/C++ مع واجهة برمجة تطبيقات نظيفة، ماكرو تأكيد مدمج، كشف تسرب، وتطوير نشط — مثالي للأنظمة القديمة أو الحديثة.

  • كيف تقوم ببناء مشروع أساسي باستخدام CppUTest؟

    src/
      code/
        code.cpp
        code.h
      main.cpp
    t/
      main.cpp (test runner)
      test.cpp (test suite)
  • كيف يمكنك تشغيل جميع الاختبارات؟

    يستخدم مشغل الاختبار:

    return CommandLineTestRunner::RunAllTests(ac, av);
  • كيف تبني اختبارات دون تكوين خيارات المُجمِّع يدويًا؟

    استخدم MakefileWorker.mk من CppUTest، والذي يتولى إدارة العلامات، والربط، وتنفيذ الاختبارات تلقائيًا.

  • هل يمكن لـ CppUTest اكتشاف تسربات الذاكرة تلقائيًا؟

    نعم. إنه يتجاوز malloc/free خلال إصدارات الاختبار، ويبلغ عن:

    • أي اختبار تسبب في التسرب،

    • أين حدث،

    • حجم التسرب ومحتويات الذاكرة.

    مثال على إخراج فشل:

    Memory leak(s) found.
    Allocated at: code.c line 6
    Leak size: 1
  • كيف يمكنني إنشاء تغطية للكود؟

    1. تمكين: CPPUTEST_USE_GCOV=Y

    2. تأكد من أن filterGcov.sh متاح في $(CPPUTEST_HOME)/scripts/.

    3. تشغيل: make gcov

      يتم إنتاج .gcov، نص ملخص، وتغطية تقارير HTML.

  • ماذا يمكن أن يفعل CppUTest أيضًا بخلاف الاختبارات الأساسية؟

    • إطار عمل للتزييف

    • نظام الإضافات

    • برامج تلقائية للمساعدة

    • تكامل C الأصلي

    • ماكرو تأكيد واسع النطاق

  • لمن يعد CppUTest الأنسب؟

    الفرق التي تعمل مع الأنظمة المدمجة، منصات C، خدمات C++، أو أي بيئة حيث يجب التحقق باستمرار من الموثوقية وسلامة الذاكرة.

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

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

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

تحميل CppUTest

صفحة مشروع CppUTest متاحة على الموقع الرسمي، والمستودع موجود على github. كما أنه مدرج في مستودعات إدارة الحزم للعديد من توزيعات نظام لينكس، وكذلك homebrew على نظام Mac OS. الأمثلة التالية نُفذت على Mac OS X، لكنها مشتقة من كود مكتوب لنظام Red Hat، النظام الذي تعمل عليه منصتنا.

الأساسيات موثقة جيدًا على الصفحة الرئيسية لـCppUTest. سنستعرضها بسرعة وننتقل إلى بعض الميزات الأكثر إثارة للاهتمام.

صفحة مشروع CppUTest متاحة على الموقع الرسمي، والمستودع موجود على github. كما أنه مدرج في مستودعات إدارة الحزم للعديد من توزيعات نظام لينكس، وكذلك homebrew على نظام Mac OS. الأمثلة التالية نُفذت على Mac OS X، لكنها مشتقة من كود مكتوب لنظام Red Hat، النظام الذي تعمل عليه منصتنا.

الأساسيات موثقة جيدًا على الصفحة الرئيسية لـCppUTest. سنستعرضها بسرعة وننتقل إلى بعض الميزات الأكثر إثارة للاهتمام.

صفحة مشروع CppUTest متاحة على الموقع الرسمي، والمستودع موجود على github. كما أنه مدرج في مستودعات إدارة الحزم للعديد من توزيعات نظام لينكس، وكذلك homebrew على نظام Mac OS. الأمثلة التالية نُفذت على Mac OS X، لكنها مشتقة من كود مكتوب لنظام Red Hat، النظام الذي تعمل عليه منصتنا.

الأساسيات موثقة جيدًا على الصفحة الرئيسية لـCppUTest. سنستعرضها بسرعة وننتقل إلى بعض الميزات الأكثر إثارة للاهتمام.

وضع الأساس

أولاً وقبل كل شيء، لنكتب بعض الأكواد!

مشروع الاختبار لدينا سيكون به ملف 'main' وسيشمل مكتبة أدوات تُسمى 'code'. ستوفر المكتبة وظيفة بسيطة تُعيد القيمة 1 (حالياً). ستكون الملفات موزعة على النحو التالي:

├── src
├── code
├── code.cpp
└── code.h
└── main.cpp
└── t
    ├── main.cpp
    └── test.cpp

لنبدأ بكتابة الملفات الموجودة في src/

// src/main.cpp
#include <stdlib.h>
#include <stdio.h>
#include "code.h"
int main(void) {
    test_func();
    printf("hello world!\n");
    exit(0);
}


// src/code/code.cpp
#include <stdlib.h>
#include "code.h"
int test_func() {
    return 1;
}


// src/code/code.h
#ifndef __code_h__
#define __code_h__
int test_func();
#endif

الآن، لنقم بإجراء الاختبارات، والتي ستكون في دليل t/.  أول شيء يجب فعله هو إعداد مشغل اختبارات يقوم بتشغيل ملفات الاختبار الخاصة بنا. هذا أيضاً هو وظيفة 'main'  التي سيتم تنفيذها بمجرد تجميع كل هذا:

// t/main.cpp
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av) {
return CommandLineTestRunner::RunAllTests(ac, av);
}

الآن يمكننا كتابة أول وحدة اختبار لدينا:

// t/test.cpp
#include "CppUTest/TestHarness.h"
#include "code.h"
TEST_GROUP(AwesomeExamples)
{
};
TEST(AwesomeExamples, FirstExample)
{
    int x = test_func();
    CHECK_EQUAL(1, x);
}

التالي، نحتاج إلى كتابة ملفات Makefiles.  سنحتاج اثنين: واحد لملفات المشروع تحت src/، وواحد للاختبارات.

أولاً وقبل كل شيء، لنكتب بعض الأكواد!

مشروع الاختبار لدينا سيكون به ملف 'main' وسيشمل مكتبة أدوات تُسمى 'code'. ستوفر المكتبة وظيفة بسيطة تُعيد القيمة 1 (حالياً). ستكون الملفات موزعة على النحو التالي:

├── src
├── code
├── code.cpp
└── code.h
└── main.cpp
└── t
    ├── main.cpp
    └── test.cpp

لنبدأ بكتابة الملفات الموجودة في src/

// src/main.cpp
#include <stdlib.h>
#include <stdio.h>
#include "code.h"
int main(void) {
    test_func();
    printf("hello world!\n");
    exit(0);
}


// src/code/code.cpp
#include <stdlib.h>
#include "code.h"
int test_func() {
    return 1;
}


// src/code/code.h
#ifndef __code_h__
#define __code_h__
int test_func();
#endif

الآن، لنقم بإجراء الاختبارات، والتي ستكون في دليل t/.  أول شيء يجب فعله هو إعداد مشغل اختبارات يقوم بتشغيل ملفات الاختبار الخاصة بنا. هذا أيضاً هو وظيفة 'main'  التي سيتم تنفيذها بمجرد تجميع كل هذا:

// t/main.cpp
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av) {
return CommandLineTestRunner::RunAllTests(ac, av);
}

الآن يمكننا كتابة أول وحدة اختبار لدينا:

// t/test.cpp
#include "CppUTest/TestHarness.h"
#include "code.h"
TEST_GROUP(AwesomeExamples)
{
};
TEST(AwesomeExamples, FirstExample)
{
    int x = test_func();
    CHECK_EQUAL(1, x);
}

التالي، نحتاج إلى كتابة ملفات Makefiles.  سنحتاج اثنين: واحد لملفات المشروع تحت src/، وواحد للاختبارات.

أولاً وقبل كل شيء، لنكتب بعض الأكواد!

مشروع الاختبار لدينا سيكون به ملف 'main' وسيشمل مكتبة أدوات تُسمى 'code'. ستوفر المكتبة وظيفة بسيطة تُعيد القيمة 1 (حالياً). ستكون الملفات موزعة على النحو التالي:

├── src
├── code
├── code.cpp
└── code.h
└── main.cpp
└── t
    ├── main.cpp
    └── test.cpp

لنبدأ بكتابة الملفات الموجودة في src/

// src/main.cpp
#include <stdlib.h>
#include <stdio.h>
#include "code.h"
int main(void) {
    test_func();
    printf("hello world!\n");
    exit(0);
}


// src/code/code.cpp
#include <stdlib.h>
#include "code.h"
int test_func() {
    return 1;
}


// src/code/code.h
#ifndef __code_h__
#define __code_h__
int test_func();
#endif

الآن، لنقم بإجراء الاختبارات، والتي ستكون في دليل t/.  أول شيء يجب فعله هو إعداد مشغل اختبارات يقوم بتشغيل ملفات الاختبار الخاصة بنا. هذا أيضاً هو وظيفة 'main'  التي سيتم تنفيذها بمجرد تجميع كل هذا:

// t/main.cpp
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av) {
return CommandLineTestRunner::RunAllTests(ac, av);
}

الآن يمكننا كتابة أول وحدة اختبار لدينا:

// t/test.cpp
#include "CppUTest/TestHarness.h"
#include "code.h"
TEST_GROUP(AwesomeExamples)
{
};
TEST(AwesomeExamples, FirstExample)
{
    int x = test_func();
    CHECK_EQUAL(1, x);
}

التالي، نحتاج إلى كتابة ملفات Makefiles.  سنحتاج اثنين: واحد لملفات المشروع تحت src/، وواحد للاختبارات.

مشروع Makefile

سيكون ملف المشروع عند نفس مستوى الأدلة 'src' و 't' في جذر المشروع. يجب أن يبدو مثل هذا:

# Makefile

SRC_DIR = ./src
CODE_DIR = $(SRC_DIR)/code
OUT = example
TEST_DIR = t

test:
make -C $(TEST_DIR)

test_clean:
make -C $(TEST_DIR) clean

code.o:
gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o

main: code.o
gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT)

all: test main

clean: test_clean
rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)

لاحظ أن هذا يستخدم ‘make -C’ للأهداف التجريبية – مما يعني أنه سيستدعي ‘make’ مرة أخرى باستخدام ملف makefile في دليل الاختبار.

في هذه المرحلة يمكننا ترجمة كود ‘src’ باستخدام ملف makefile ونرى أنه يعمل:

[]$ make main
gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o
gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example
[]$ ./example
hello world

سيكون ملف المشروع عند نفس مستوى الأدلة 'src' و 't' في جذر المشروع. يجب أن يبدو مثل هذا:

# Makefile

SRC_DIR = ./src
CODE_DIR = $(SRC_DIR)/code
OUT = example
TEST_DIR = t

test:
make -C $(TEST_DIR)

test_clean:
make -C $(TEST_DIR) clean

code.o:
gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o

main: code.o
gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT)

all: test main

clean: test_clean
rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)

لاحظ أن هذا يستخدم ‘make -C’ للأهداف التجريبية – مما يعني أنه سيستدعي ‘make’ مرة أخرى باستخدام ملف makefile في دليل الاختبار.

في هذه المرحلة يمكننا ترجمة كود ‘src’ باستخدام ملف makefile ونرى أنه يعمل:

[]$ make main
gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o
gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example
[]$ ./example
hello world

سيكون ملف المشروع عند نفس مستوى الأدلة 'src' و 't' في جذر المشروع. يجب أن يبدو مثل هذا:

# Makefile

SRC_DIR = ./src
CODE_DIR = $(SRC_DIR)/code
OUT = example
TEST_DIR = t

test:
make -C $(TEST_DIR)

test_clean:
make -C $(TEST_DIR) clean

code.o:
gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o

main: code.o
gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT)

all: test main

clean: test_clean
rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)

لاحظ أن هذا يستخدم ‘make -C’ للأهداف التجريبية – مما يعني أنه سيستدعي ‘make’ مرة أخرى باستخدام ملف makefile في دليل الاختبار.

في هذه المرحلة يمكننا ترجمة كود ‘src’ باستخدام ملف makefile ونرى أنه يعمل:

[]$ make main
gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o
gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example
[]$ ./example
hello world

اختبارات Makefile

بالنسبة للاختبارات، الأمور تكون أكثر تعقيدًا قليلاً لأننا نحتاج إلى تحميل ودمج مكتبة CppUTest بشكل صحيح.

يوفر مستودع CppUTest ملفًا يسمى “MakefileWorker.mk”. يوفر الكثير من الوظائف التي تجعل البناء باستخدام CppUTest بسيطًا. الملف يوجد تحت دليل “build” في مستودع git. بالنسبة لهذا الدرس، سنفترض أنه تم نسخه إلى الدليل 't/'. يمكن استخدامه كما يلي:

# we don’t want to use relative paths, so we set these variables
PROJECT_DIR=/path/to/project
SRC_DIR=$(PROJECT_DIR)/src
TEST_DIR=$(PROJECT_DIR)/t

# specify where the source code and includes are located
INCLUDE_DIRS=$(SRC_DIR)/code
SRC_DIRS=$(SRC_DIR)/code

# specify where the test code is located
TEST_SRC_DIRS=$(TEST_DIR)

# what to call the test binary
TEST_TARGET=example

# where the cpputest library is located
CPPUTEST_HOME=/usr/local

# run MakefileWorker.mk with the variables defined here
include MakefileWorker.mk

لاحظ أن CPPUTEST_HOME يجب أن يتم تعيينه إلى المكان الذي تم تثبيت CppUTest فيه. إذا قمت بتثبيت حزمة توزيعة، فإن هذا سيكون عادةً تحت /usr/local في نظام لينكس/ماك. إذا قمت بتسجيل الخروج من المستودع بنفسك، فهو المكان الذي يوجد فيه.

تم توثيق كل هذه الخيارات في MakefileWorker.mk.

MakefileWorker.mk يضيف أيضا بعض الأهداف إلى makefile، بما في ذلك ما يلي:

  1. all – يبني الاختبارات المشار إليها بواسطة makefile

  2. clean – يزيل كل الملفات الهدف وملفات gcov المولدة للاختبارات

  3. realclean – يزيل أي ملفات هدف أو ملفات gcov في شجرة الدليل بأكملها

  4. flags – يسرد كل العلامات المكوّنة المستخدمة لتجميع الاختبارات

  5. debug – يسرد جميع ملفات المصدر، والكائنات، والاعتماديات، و"الأشياء للتنظيف"

بالنسبة للاختبارات، الأمور تكون أكثر تعقيدًا قليلاً لأننا نحتاج إلى تحميل ودمج مكتبة CppUTest بشكل صحيح.

يوفر مستودع CppUTest ملفًا يسمى “MakefileWorker.mk”. يوفر الكثير من الوظائف التي تجعل البناء باستخدام CppUTest بسيطًا. الملف يوجد تحت دليل “build” في مستودع git. بالنسبة لهذا الدرس، سنفترض أنه تم نسخه إلى الدليل 't/'. يمكن استخدامه كما يلي:

# we don’t want to use relative paths, so we set these variables
PROJECT_DIR=/path/to/project
SRC_DIR=$(PROJECT_DIR)/src
TEST_DIR=$(PROJECT_DIR)/t

# specify where the source code and includes are located
INCLUDE_DIRS=$(SRC_DIR)/code
SRC_DIRS=$(SRC_DIR)/code

# specify where the test code is located
TEST_SRC_DIRS=$(TEST_DIR)

# what to call the test binary
TEST_TARGET=example

# where the cpputest library is located
CPPUTEST_HOME=/usr/local

# run MakefileWorker.mk with the variables defined here
include MakefileWorker.mk

لاحظ أن CPPUTEST_HOME يجب أن يتم تعيينه إلى المكان الذي تم تثبيت CppUTest فيه. إذا قمت بتثبيت حزمة توزيعة، فإن هذا سيكون عادةً تحت /usr/local في نظام لينكس/ماك. إذا قمت بتسجيل الخروج من المستودع بنفسك، فهو المكان الذي يوجد فيه.

تم توثيق كل هذه الخيارات في MakefileWorker.mk.

MakefileWorker.mk يضيف أيضا بعض الأهداف إلى makefile، بما في ذلك ما يلي:

  1. all – يبني الاختبارات المشار إليها بواسطة makefile

  2. clean – يزيل كل الملفات الهدف وملفات gcov المولدة للاختبارات

  3. realclean – يزيل أي ملفات هدف أو ملفات gcov في شجرة الدليل بأكملها

  4. flags – يسرد كل العلامات المكوّنة المستخدمة لتجميع الاختبارات

  5. debug – يسرد جميع ملفات المصدر، والكائنات، والاعتماديات، و"الأشياء للتنظيف"

بالنسبة للاختبارات، الأمور تكون أكثر تعقيدًا قليلاً لأننا نحتاج إلى تحميل ودمج مكتبة CppUTest بشكل صحيح.

يوفر مستودع CppUTest ملفًا يسمى “MakefileWorker.mk”. يوفر الكثير من الوظائف التي تجعل البناء باستخدام CppUTest بسيطًا. الملف يوجد تحت دليل “build” في مستودع git. بالنسبة لهذا الدرس، سنفترض أنه تم نسخه إلى الدليل 't/'. يمكن استخدامه كما يلي:

# we don’t want to use relative paths, so we set these variables
PROJECT_DIR=/path/to/project
SRC_DIR=$(PROJECT_DIR)/src
TEST_DIR=$(PROJECT_DIR)/t

# specify where the source code and includes are located
INCLUDE_DIRS=$(SRC_DIR)/code
SRC_DIRS=$(SRC_DIR)/code

# specify where the test code is located
TEST_SRC_DIRS=$(TEST_DIR)

# what to call the test binary
TEST_TARGET=example

# where the cpputest library is located
CPPUTEST_HOME=/usr/local

# run MakefileWorker.mk with the variables defined here
include MakefileWorker.mk

لاحظ أن CPPUTEST_HOME يجب أن يتم تعيينه إلى المكان الذي تم تثبيت CppUTest فيه. إذا قمت بتثبيت حزمة توزيعة، فإن هذا سيكون عادةً تحت /usr/local في نظام لينكس/ماك. إذا قمت بتسجيل الخروج من المستودع بنفسك، فهو المكان الذي يوجد فيه.

تم توثيق كل هذه الخيارات في MakefileWorker.mk.

MakefileWorker.mk يضيف أيضا بعض الأهداف إلى makefile، بما في ذلك ما يلي:

  1. all – يبني الاختبارات المشار إليها بواسطة makefile

  2. clean – يزيل كل الملفات الهدف وملفات gcov المولدة للاختبارات

  3. realclean – يزيل أي ملفات هدف أو ملفات gcov في شجرة الدليل بأكملها

  4. flags – يسرد كل العلامات المكوّنة المستخدمة لتجميع الاختبارات

  5. debug – يسرد جميع ملفات المصدر، والكائنات، والاعتماديات، و"الأشياء للتنظيف"

تغطية الشفرة

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

CPPUTEST_USE_GCOV=Y

التالي، نحتاج للتأكد من أن سكربت filterGcov.sh من هذا المستودع موجود في ‘/scripts/filterGcov.sh’ بالنسبة للموقع الذي حددت فيه ‘CPPUTEST_HOME’. يجب أيضًا أن يكون لديه أذونات التنفيذ.

في مثال ملف Makefile، سيتم نشره في ‘/usr/local/scripts/filterGcov.sh’. إذا كنت تقوم بتشغيل CppUTest من مستودع، يجب أن يعمل كل شيء دون تعديل.

مع كل ذلك في مكانه، يمكنك ببساطة تشغيل ‘make gcov’ وسيتم توليد التحليل لك. في حالتنا، سنحتاج إلى ‘make -B’ لإعادة بناء ملفات الأجسام مع تمكين gcov:

[]$ make -B gcov
< compilation output >

for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \
    FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \
    gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \
done

for f in  ; do \
    gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \
done

/usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt

cat gcov_report.txt
100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp

mkdir -p gcov
mv *.gcov gcov
mv gcov_* gcov

See gcov directory for details

هذا سوف ينتج عددًا من الملفات في دليل جديد يسمى ‘gcov’. هذه الملفات هي:

  1. code.cpp.gcov – الملف الفعلي ‘gcov’ للشفرة التي تم اختبارها

  2. gcov_error.txt – تقرير الأخطاء (في حالتنا، ينبغي أن يكون فارغًا)

  3. gcov_output.txt – المخرجات الفعلية لأمر gcov الذي تم تشغيله

  4. gcov_report.txt – ملخص لتغطية كل ملف تحت الاختبار

  5. gcov_report.txt.html – نسخة html من gcov_report

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

CPPUTEST_USE_GCOV=Y

التالي، نحتاج للتأكد من أن سكربت filterGcov.sh من هذا المستودع موجود في ‘/scripts/filterGcov.sh’ بالنسبة للموقع الذي حددت فيه ‘CPPUTEST_HOME’. يجب أيضًا أن يكون لديه أذونات التنفيذ.

في مثال ملف Makefile، سيتم نشره في ‘/usr/local/scripts/filterGcov.sh’. إذا كنت تقوم بتشغيل CppUTest من مستودع، يجب أن يعمل كل شيء دون تعديل.

مع كل ذلك في مكانه، يمكنك ببساطة تشغيل ‘make gcov’ وسيتم توليد التحليل لك. في حالتنا، سنحتاج إلى ‘make -B’ لإعادة بناء ملفات الأجسام مع تمكين gcov:

[]$ make -B gcov
< compilation output >

for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \
    FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \
    gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \
done

for f in  ; do \
    gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \
done

/usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt

cat gcov_report.txt
100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp

mkdir -p gcov
mv *.gcov gcov
mv gcov_* gcov

See gcov directory for details

هذا سوف ينتج عددًا من الملفات في دليل جديد يسمى ‘gcov’. هذه الملفات هي:

  1. code.cpp.gcov – الملف الفعلي ‘gcov’ للشفرة التي تم اختبارها

  2. gcov_error.txt – تقرير الأخطاء (في حالتنا، ينبغي أن يكون فارغًا)

  3. gcov_output.txt – المخرجات الفعلية لأمر gcov الذي تم تشغيله

  4. gcov_report.txt – ملخص لتغطية كل ملف تحت الاختبار

  5. gcov_report.txt.html – نسخة html من gcov_report

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

CPPUTEST_USE_GCOV=Y

التالي، نحتاج للتأكد من أن سكربت filterGcov.sh من هذا المستودع موجود في ‘/scripts/filterGcov.sh’ بالنسبة للموقع الذي حددت فيه ‘CPPUTEST_HOME’. يجب أيضًا أن يكون لديه أذونات التنفيذ.

في مثال ملف Makefile، سيتم نشره في ‘/usr/local/scripts/filterGcov.sh’. إذا كنت تقوم بتشغيل CppUTest من مستودع، يجب أن يعمل كل شيء دون تعديل.

مع كل ذلك في مكانه، يمكنك ببساطة تشغيل ‘make gcov’ وسيتم توليد التحليل لك. في حالتنا، سنحتاج إلى ‘make -B’ لإعادة بناء ملفات الأجسام مع تمكين gcov:

[]$ make -B gcov
< compilation output >

for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \
    FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \
    gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \
done

for f in  ; do \
    gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \
done

/usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt

cat gcov_report.txt
100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp

mkdir -p gcov
mv *.gcov gcov
mv gcov_* gcov

See gcov directory for details

هذا سوف ينتج عددًا من الملفات في دليل جديد يسمى ‘gcov’. هذه الملفات هي:

  1. code.cpp.gcov – الملف الفعلي ‘gcov’ للشفرة التي تم اختبارها

  2. gcov_error.txt – تقرير الأخطاء (في حالتنا، ينبغي أن يكون فارغًا)

  3. gcov_output.txt – المخرجات الفعلية لأمر gcov الذي تم تشغيله

  4. gcov_report.txt – ملخص لتغطية كل ملف تحت الاختبار

  5. gcov_report.txt.html – نسخة html من gcov_report

اكتشاف تسرب الذاكرة Cpputest

يسمح لك Cpputest بالكشف تلقائيًا عن الذاكرة المسربة عن طريق إعادة تعريف عائلة دوال “malloc/free” القياسية لاستخدام الأغراض التعليمية بدلاً من ذلك. يتيح ذلك له اكتشاف التسريبات بسرعة والإبلاغ عنها لكل تنفيذ اختبار. يتم تمكين هذا افتراضيًا في MakefileWorker.mk، لذا فهو مفعل بالفعل مع الخطوات الموضحة حتى الآن.

لتوضيح ذلك، دَعنا نسرب بعض الذاكرة في test_func() !

بالعودة إلى code.c، نضيف malloc()  إلى الدالة، كما يلي:

int test_func() {
    malloc(1);
    return 1;
}

الآن، بعد إعادة الترجمة، يتم إنتاج الخطأ التالي:

test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample)
Memory leak(s) found.
Alloc num (4)
Leak size: 1
Allocated at: ./code.c and line: 6
Type: "malloc"
Memory: <

هذا يحدد أي اختبار تسبب في التسريب، وأين حدث التسريب في كود المصدر، وما كان في الذاكرة المسربة. مفيد جدًا!

هناك بعض التحذيرات مع هذه الميزة:

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

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

CPPUTEST_USE_MEM_LEAK_DETECTION=N

يسمح لك Cpputest بالكشف تلقائيًا عن الذاكرة المسربة عن طريق إعادة تعريف عائلة دوال “malloc/free” القياسية لاستخدام الأغراض التعليمية بدلاً من ذلك. يتيح ذلك له اكتشاف التسريبات بسرعة والإبلاغ عنها لكل تنفيذ اختبار. يتم تمكين هذا افتراضيًا في MakefileWorker.mk، لذا فهو مفعل بالفعل مع الخطوات الموضحة حتى الآن.

لتوضيح ذلك، دَعنا نسرب بعض الذاكرة في test_func() !

بالعودة إلى code.c، نضيف malloc()  إلى الدالة، كما يلي:

int test_func() {
    malloc(1);
    return 1;
}

الآن، بعد إعادة الترجمة، يتم إنتاج الخطأ التالي:

test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample)
Memory leak(s) found.
Alloc num (4)
Leak size: 1
Allocated at: ./code.c and line: 6
Type: "malloc"
Memory: <

هذا يحدد أي اختبار تسبب في التسريب، وأين حدث التسريب في كود المصدر، وما كان في الذاكرة المسربة. مفيد جدًا!

هناك بعض التحذيرات مع هذه الميزة:

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

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

CPPUTEST_USE_MEM_LEAK_DETECTION=N

يسمح لك Cpputest بالكشف تلقائيًا عن الذاكرة المسربة عن طريق إعادة تعريف عائلة دوال “malloc/free” القياسية لاستخدام الأغراض التعليمية بدلاً من ذلك. يتيح ذلك له اكتشاف التسريبات بسرعة والإبلاغ عنها لكل تنفيذ اختبار. يتم تمكين هذا افتراضيًا في MakefileWorker.mk، لذا فهو مفعل بالفعل مع الخطوات الموضحة حتى الآن.

لتوضيح ذلك، دَعنا نسرب بعض الذاكرة في test_func() !

بالعودة إلى code.c، نضيف malloc()  إلى الدالة، كما يلي:

int test_func() {
    malloc(1);
    return 1;
}

الآن، بعد إعادة الترجمة، يتم إنتاج الخطأ التالي:

test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample)
Memory leak(s) found.
Alloc num (4)
Leak size: 1
Allocated at: ./code.c and line: 6
Type: "malloc"
Memory: <

هذا يحدد أي اختبار تسبب في التسريب، وأين حدث التسريب في كود المصدر، وما كان في الذاكرة المسربة. مفيد جدًا!

هناك بعض التحذيرات مع هذه الميزة:

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

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

CPPUTEST_USE_MEM_LEAK_DETECTION=N

مهتم بمعرفة المزيد؟

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

آمل أن تساعدك المعلومات هنا في تحسين جودة كود C/C++ باستخدام هذه الأداة الرائعة!

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

آمل أن تساعدك المعلومات هنا في تحسين جودة كود C/C++ باستخدام هذه الأداة الرائعة!

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

آمل أن تساعدك المعلومات هنا في تحسين جودة كود C/C++ باستخدام هذه الأداة الرائعة!

أخبار أخرى

اقرأ المزيد من هذه الفئة

A person is standing at a desk while typing on a laptop.

المنصة الأصلية للذكاء الاصطناعي التي تتوسع مع عملك.

A person is standing at a desk while typing on a laptop.

المنصة الأصلية للذكاء الاصطناعي التي تتوسع مع عملك.

A person is standing at a desk while typing on a laptop.

المنصة الأصلية للذكاء الاصطناعي التي تتوسع مع عملك.